[
  {
    "path": ".appveyor.yml",
    "content": "init:\n- git config --global core.autocrlf true\nbranches:\n  only:\n  - master\n  - /^release\\/.*$/\n  - /^(.*\\/)?ci-.*$/\nbuild_script:\n- ps: .\\run.ps1 default-build\nclone_depth: 1\nenvironment:\n  global:\n    DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true\n    DOTNET_CLI_TELEMETRY_OPTOUT: 1\ntest: 'off'\ndeploy: 'off'\nos: Visual Studio 2017\n"
  },
  {
    "path": ".editorconfig",
    "content": "﻿# EditorConfig is awesome:http://EditorConfig.org\n\n# top-most EditorConfig file\nroot = true\n\n[*]\nindent_style = space\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.cs]\nindent_size = 4\ndotnet_sort_system_directives_first = true:warning\n\n# Xml files\n[*.{csproj,config,props,targets,ruleset,config,resx,xml}]\nindent_size = 2\n\n[*.{json, yml}]\nindent_size = 2\n\n[*.{ps1,sh}]\nindent_size = 4"
  },
  {
    "path": ".gitattributes",
    "content": "*.doc  diff=astextplain\n*.DOC\tdiff=astextplain\n*.docx\tdiff=astextplain\n*.DOCX\tdiff=astextplain\n*.dot\tdiff=astextplain\n*.DOT\tdiff=astextplain\n*.pdf\tdiff=astextplain\n*.PDF\tdiff=astextplain\n*.rtf\tdiff=astextplain\n*.RTF\tdiff=astextplain\n\n*.jpg  \tbinary\n*.png \tbinary\n*.gif \tbinary\n\n*.cs text=auto diff=csharp \n*.vb text=auto\n*.resx text=auto\n*.c text=auto\n*.cpp text=auto\n*.cxx text=auto\n*.h text=auto\n*.hxx text=auto\n*.py text=auto\n*.rb text=auto\n*.java text=auto\n*.html text=auto\n*.htm text=auto\n*.css text=auto\n*.scss text=auto\n*.sass text=auto\n*.less text=auto\n*.js text=auto\n*.lisp text=auto\n*.clj text=auto\n*.sql text=auto\n*.php text=auto\n*.lua text=auto\n*.m text=auto\n*.asm text=auto\n*.erl text=auto\n*.fs text=auto\n*.fsx text=auto\n*.hs text=auto\n\n*.csproj text=auto\n*.vbproj text=auto\n*.fsproj text=auto\n*.dbproj text=auto\n*.sln text=auto eol=crlf\n\n*.sh eol=lf"
  },
  {
    "path": ".gitignore",
    "content": "[Oo]bj/\n[Bb]in/\nTestResults/\n.nuget/\n_ReSharper.*/\npackages/\nartifacts/\nPublishProfiles/\n*.user\n*.suo\n*.cache\n*.docstates\n_ReSharper.*\nnuget.exe\n*net45.csproj\n*net451.csproj\n*k10.csproj\n*.psess\n*.vsp\n*.pidb\n*.userprefs\n*DS_Store\n*.ncrunchsolution\n*.*sdf\n*.ipch\n*.sln.ide\nproject.lock.json\n.testPublish/\n.build/\n/.vs/\n.vscode/\n*.nuget.props\n*.nuget.targets\n.idea/\n.dotnet/\nglobal.json\n*.binlog\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: csharp\nsudo: false\ndist: trusty\nenv:\n  global:\n  - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true\n  - DOTNET_CLI_TELEMETRY_OPTOUT: 1\nmono: none\nos:\n- linux\n- osx\nosx_image: xcode8.2\naddons:\n  apt:\n    packages:\n    - libunwind8\nbranches:\n  only:\n  - master\n  - /^release\\/.*$/\n  - /^(.*\\/)?ci-.*$/\nbefore_install:\n- if test \"$TRAVIS_OS_NAME\" == \"osx\"; then brew update; brew install openssl; ln -s\n  /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\n  /usr/local/lib/; fi\nscript:\n- ./build.sh\n"
  },
  {
    "path": ".vsts-pipelines/builds/ci-internal.yml",
    "content": "trigger:\n- master\n- release/*\n\nresources:\n  repositories:\n  - repository: buildtools\n    type: git\n    name: aspnet-BuildTools\n    ref: refs/heads/master\n\nphases:\n- template: .vsts-pipelines/templates/project-ci.yml@buildtools\n"
  },
  {
    "path": ".vsts-pipelines/builds/ci-public.yml",
    "content": "trigger:\n- master\n- release/*\n\n# See https://github.com/aspnet/BuildTools\nresources:\n  repositories:\n  - repository: buildtools\n    type: github\n    endpoint: DotNet-Bot GitHub Connection\n    name: aspnet/BuildTools\n    ref: refs/heads/master\n\nphases:\n- template: .vsts-pipelines/templates/project-ci.yml@buildtools\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "Contributing\n======\n\nInformation on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/master/CONTRIBUTING.md) in the Home repo.\n"
  },
  {
    "path": "Directory.Build.props",
    "content": "<Project>\n  <Import\n    Project=\"$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), AspNetCoreSettings.props))\\AspNetCoreSettings.props\"\n    Condition=\" '$(CI)' != 'true' AND '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), AspNetCoreSettings.props))' != '' \" />\n\n  <Import Project=\"version.props\" />\n  <Import Project=\"build\\dependencies.props\" />\n  <Import Project=\"build\\sources.props\" />\n\n  <PropertyGroup>\n    <Product>Microsoft .NET</Product>\n    <RepositoryUrl>https://github.com/aspnet/DotNetTools</RepositoryUrl>\n    <RepositoryType>git</RepositoryType>\n    <RepositoryRoot>$(MSBuildThisFileDirectory)</RepositoryRoot>\n    <AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)build\\Key.snk</AssemblyOriginatorKeyFile>\n    <SignAssembly>true</SignAssembly>\n    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>\n\n    <!-- Binary compatiblity is not a goal for command-line tools. -->\n    <EnableApiCheck>false</EnableApiCheck>\n    <BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)obj\\$(MSBuildProjectName)\\</BaseIntermediateOutputPath>\n    <BaseOutputPath>$(MSBuildThisFileDirectory)bin\\$(MSBuildProjectName)\\</BaseOutputPath>\n  </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "Directory.Build.targets",
    "content": "<Project>\n  <PropertyGroup>\n    <RuntimeFrameworkVersion Condition=\" '$(TargetFramework)' == 'netcoreapp3.0' \">$(MicrosoftNETCoreApp30PackageVersion)</RuntimeFrameworkVersion>\n    <NETStandardImplicitPackageVersion Condition=\" '$(TargetFramework)' == 'netstandard2.0' \">$(NETStandardLibrary20PackageVersion)</NETStandardImplicitPackageVersion>\n    <!-- aspnet/BuildTools#662 Don't police what version of NetCoreApp we use -->\n    <NETCoreAppMaximumVersion>99.9</NETCoreAppMaximumVersion>\n  </PropertyGroup>\n</Project>\n"
  },
  {
    "path": "DotNetTools.sln",
    "content": "Microsoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio 15\r\nVisualStudioVersion = 15.0.27120.0\r\nMinimumVisualStudioVersion = 15.0.26730.03\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"src\", \"src\", \"{66517987-2A5A-4330-B130-207039378FD4}\"\r\n\tProjectSection(SolutionItems) = preProject\r\n\t\tsrc\\Directory.Build.props = src\\Directory.Build.props\r\n\tEndProjectSection\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"dotnet-watch\", \"src\\dotnet-watch\\dotnet-watch.csproj\", \"{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}\"\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Solution Items\", \"Solution Items\", \"{8321E0D1-9A47-4D2F-AED8-3AE636D44E35}\"\r\n\tProjectSection(SolutionItems) = preProject\r\n\t\t.appveyor.yml = .appveyor.yml\r\n\t\t.editorconfig = .editorconfig\r\n\t\t.gitattributes = .gitattributes\r\n\t\t.gitignore = .gitignore\r\n\t\t.travis.yml = .travis.yml\r\n\t\tbuild.cmd = build.cmd\r\n\t\tbuild.ps1 = build.ps1\r\n\t\tbuild.sh = build.sh\r\n\t\tCONTRIBUTING.md = CONTRIBUTING.md\r\n\t\tbuild\\dependencies.props = build\\dependencies.props\r\n\t\tDirectory.Build.props = Directory.Build.props\r\n\t\tDirectory.Build.targets = Directory.Build.targets\r\n\t\tLICENSE.txt = LICENSE.txt\r\n\t\tNuGet.config = NuGet.config\r\n\t\tNuGetPackageVerifier.json = NuGetPackageVerifier.json\r\n\t\tREADME.md = README.md\r\n\t\tbuild\\sources.props = build\\sources.props\r\n\t\tversion.props = version.props\r\n\tEndProjectSection\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"test\", \"test\", \"{F5B382BC-258F-46E1-AC3D-10E5CCD55134}\"\r\n\tProjectSection(SolutionItems) = preProject\r\n\t\ttest\\Directory.Build.props = test\\Directory.Build.props\r\n\tEndProjectSection\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"dotnet-watch.FunctionalTests\", \"test\\dotnet-watch.FunctionalTests\\dotnet-watch.FunctionalTests.csproj\", \"{16BADE2F-1184-4518-8A70-B68A19D0805B}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"dotnet-user-secrets\", \"src\\dotnet-user-secrets\\dotnet-user-secrets.csproj\", \"{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"dotnet-user-secrets.Tests\", \"test\\dotnet-user-secrets.Tests\\dotnet-user-secrets.Tests.csproj\", \"{7B331122-83B1-4F08-A119-DC846959844C}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"dotnet-watch.Tests\", \"test\\dotnet-watch.Tests\\dotnet-watch.Tests.csproj\", \"{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"dotnet-sql-cache\", \"src\\dotnet-sql-cache\\dotnet-sql-cache.csproj\", \"{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"dotnet-dev-certs\", \"src\\dotnet-dev-certs\\dotnet-dev-certs.csproj\", \"{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}\"\r\nEndProject\r\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"Microsoft.VisualStudio.SecretManager\", \"tooling\\Microsoft.VisualStudio.SecretManager\\Microsoft.VisualStudio.SecretManager.csproj\", \"{5E117F2E-7152-447F-BF47-59F759EEF3A7}\"\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"tooling\", \"tooling\", \"{62826851-7D74-4F1E-B7D1-12553B789CD8}\"\r\nEndProject\r\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"Microsoft.VisualStudio.SecretManager.TestExtension\", \"tooling\\Microsoft.VisualStudio.SecretManager.TestExtension\\Microsoft.VisualStudio.SecretManager.TestExtension.csproj\", \"{965F8820-F809-4081-9090-1AEC903F291B}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.AspNetCore.DeveloperCertificates.XPlat\", \"src\\Microsoft.AspNetCore.DeveloperCertificates.XPlat\\Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj\", \"{96E71881-1465-44F5-B4B7-DF9B370FFD02}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.HttpRepl\", \"src\\Microsoft.HttpRepl\\Microsoft.HttpRepl.csproj\", \"{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.Repl\", \"src\\Microsoft.Repl\\Microsoft.Repl.csproj\", \"{EE9A6128-3DE2-4206-A5A4-3ED935084590}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.Repl.Tests\", \"test\\Microsoft.Repl.Tests\\Microsoft.Repl.Tests.csproj\", \"{59C2B354-3B5E-40EB-A7BC-74583A5707CA}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.HttpRepl.Tests\", \"test\\Microsoft.HttpRepl.Tests\\Microsoft.HttpRepl.Tests.csproj\", \"{BE7CC4CD-CD76-4211-B593-CAC84407162A}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|Any CPU = Debug|Any CPU\r\n\t\tDebugNoVSIX|Any CPU = DebugNoVSIX|Any CPU\r\n\t\tRelease|Any CPU = Release|Any CPU\r\n\t\tReleaseNoVSIX|Any CPU = ReleaseNoVSIX|Any CPU\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{16BADE2F-1184-4518-8A70-B68A19D0805B}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{16BADE2F-1184-4518-8A70-B68A19D0805B}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{16BADE2F-1184-4518-8A70-B68A19D0805B}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{16BADE2F-1184-4518-8A70-B68A19D0805B}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{7B331122-83B1-4F08-A119-DC846959844C}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{7B331122-83B1-4F08-A119-DC846959844C}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{7B331122-83B1-4F08-A119-DC846959844C}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{7B331122-83B1-4F08-A119-DC846959844C}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{5E117F2E-7152-447F-BF47-59F759EEF3A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{5E117F2E-7152-447F-BF47-59F759EEF3A7}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{5E117F2E-7152-447F-BF47-59F759EEF3A7}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{5E117F2E-7152-447F-BF47-59F759EEF3A7}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{5E117F2E-7152-447F-BF47-59F759EEF3A7}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{5E117F2E-7152-447F-BF47-59F759EEF3A7}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{965F8820-F809-4081-9090-1AEC903F291B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{965F8820-F809-4081-9090-1AEC903F291B}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{965F8820-F809-4081-9090-1AEC903F291B}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{965F8820-F809-4081-9090-1AEC903F291B}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{965F8820-F809-4081-9090-1AEC903F291B}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{965F8820-F809-4081-9090-1AEC903F291B}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{96E71881-1465-44F5-B4B7-DF9B370FFD02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{96E71881-1465-44F5-B4B7-DF9B370FFD02}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{96E71881-1465-44F5-B4B7-DF9B370FFD02}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{96E71881-1465-44F5-B4B7-DF9B370FFD02}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{96E71881-1465-44F5-B4B7-DF9B370FFD02}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{96E71881-1465-44F5-B4B7-DF9B370FFD02}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{96E71881-1465-44F5-B4B7-DF9B370FFD02}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{96E71881-1465-44F5-B4B7-DF9B370FFD02}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{EE9A6128-3DE2-4206-A5A4-3ED935084590}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{EE9A6128-3DE2-4206-A5A4-3ED935084590}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{EE9A6128-3DE2-4206-A5A4-3ED935084590}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{EE9A6128-3DE2-4206-A5A4-3ED935084590}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{EE9A6128-3DE2-4206-A5A4-3ED935084590}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{EE9A6128-3DE2-4206-A5A4-3ED935084590}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{EE9A6128-3DE2-4206-A5A4-3ED935084590}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{EE9A6128-3DE2-4206-A5A4-3ED935084590}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{BE7CC4CD-CD76-4211-B593-CAC84407162A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{BE7CC4CD-CD76-4211-B593-CAC84407162A}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{BE7CC4CD-CD76-4211-B593-CAC84407162A}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{BE7CC4CD-CD76-4211-B593-CAC84407162A}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{BE7CC4CD-CD76-4211-B593-CAC84407162A}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{BE7CC4CD-CD76-4211-B593-CAC84407162A}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{BE7CC4CD-CD76-4211-B593-CAC84407162A}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{BE7CC4CD-CD76-4211-B593-CAC84407162A}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\n\tGlobalSection(NestedProjects) = preSolution\r\n\t\t{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46} = {66517987-2A5A-4330-B130-207039378FD4}\r\n\t\t{16BADE2F-1184-4518-8A70-B68A19D0805B} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134}\r\n\t\t{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E} = {66517987-2A5A-4330-B130-207039378FD4}\r\n\t\t{7B331122-83B1-4F08-A119-DC846959844C} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134}\r\n\t\t{8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134}\r\n\t\t{53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4}\r\n\t\t{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8} = {66517987-2A5A-4330-B130-207039378FD4}\r\n\t\t{5E117F2E-7152-447F-BF47-59F759EEF3A7} = {62826851-7D74-4F1E-B7D1-12553B789CD8}\r\n\t\t{965F8820-F809-4081-9090-1AEC903F291B} = {62826851-7D74-4F1E-B7D1-12553B789CD8}\r\n\t\t{96E71881-1465-44F5-B4B7-DF9B370FFD02} = {66517987-2A5A-4330-B130-207039378FD4}\r\n\t\t{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D} = {66517987-2A5A-4330-B130-207039378FD4}\r\n\t\t{EE9A6128-3DE2-4206-A5A4-3ED935084590} = {66517987-2A5A-4330-B130-207039378FD4}\r\n\t\t{59C2B354-3B5E-40EB-A7BC-74583A5707CA} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134}\r\n\t\t{BE7CC4CD-CD76-4211-B593-CAC84407162A} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134}\r\n\tEndGlobalSection\r\n\tGlobalSection(ExtensibilityGlobals) = postSolution\r\n\t\tSolutionGuid = {57C07F14-2EAC-44FF-A277-B9221B4B2BF7}\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright (c) .NET Foundation and Contributors\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "NuGet.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n  <packageSources>\n    <clear />\n    <!-- Restore sources should be defined in build/sources.props. -->\n  </packageSources>\n</configuration>\n"
  },
  {
    "path": "NuGetPackageVerifier.json",
    "content": "{\r\n  \"adx\": {\r\n    \"rules\": [\r\n      \"AdxVerificationCompositeRule\"\r\n    ],\r\n    \"packages\": {\r\n      \"dotnet-watch\": {\r\n        \"packageTypes\": [\r\n          \"DotnetTool\"\r\n        ]\r\n      },\r\n      \"dotnet-sql-cache\": {\r\n        \"packageTypes\": [\r\n          \"DotnetTool\"\r\n        ]\r\n      },\r\n      \"dotnet-user-secrets\": {\r\n        \"packageTypes\": [\r\n          \"DotnetTool\"\r\n        ]\r\n      },\r\n      \"dotnet-dev-certs\": {\r\n        \"packageTypes\": [\r\n          \"DotnetTool\"\r\n        ]\r\n      },\r\n      \"Microsoft.AspNetCore.DeveloperCertificates.XPlat\": {\r\n        \"Exclusions\": {\r\n          \"DOC_MISSING\": {\r\n            \"lib/netcoreapp3.0/Microsoft.AspNetCore.DeveloperCertificates.XPlat.dll\": \"Docs not required to shipoob package\"\r\n          }\r\n        }\r\n      }\r\n    }\r\n  },\r\n  \"Default\": {\r\n    \"rules\": [\r\n      \"DefaultCompositeRule\"\r\n    ]\r\n  }\r\n}\r\n"
  },
  {
    "path": "README.md",
    "content": "DotNetTools [Archived]\n======================\n\n**This GitHub project has been archived.** Ongoing development on this project can be found in <https://github.com/aspnet/AspNetCore>.\n\nThis project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at <https://docs.asp.net>.\n\n## Projects\n\nThe repository contains command-line tools for ASP.NET Core that are bundled* in the [.NET Core CLI](https://github.com/dotnet/cli).\nFollow the links below for more details on each tool.\n\n - [dotnet-watch](src/dotnet-watch/README.md)\n - [dotnet-user-secrets](src/dotnet-user-secrets/README.md)\n - [dotnet-sql-cache](src/dotnet-sql-cache/README.md)\n - [dotnet-dev-certs](src/dotnet-dev-certs/README.md)\n\n*\\*This applies to .NET Core CLI 2.1.300-preview2 and up. For earlier versions of the CLI, these tools must be installed separately.*\n\n*For 2.0 CLI and earlier, see <https://github.com/aspnet/DotNetTools/tree/rel/2.0.0/README.md> for details.*\n\n*For 2.1.300-preview1 CLI, see <https://github.com/aspnet/DotNetTools/tree/2.1.0-preview1-final/README.md> for details.*\n\n## Usage\n\nThe command line tools can be invoked as a subcommand of `dotnet`.\n\n```sh\ndotnet watch\ndotnet user-secrets\ndotnet sql-cache\ndotnet dev-certs\n```\n\nAdd `--help` to see more details. For example,\n\n```\ndotnet watch --help\n```\n"
  },
  {
    "path": "build/VSIX.props",
    "content": "<!--\nWorkaround for https://github.com/dotnet/project-system/issues/2129 - VS does not support using MSBuild variables for PackageReference items.\nUsing a variable breaks a bunch of stuff, so this file is injected into the VSIX csproj only when building on commandline.\n-->\n<Project ToolsVersion=\"15.0\">\n  <ItemGroup>\n    <PackageReference Include=\"Newtonsoft.Json\" Version=\"$(VisualStudio_NewtonsoftJsonPackageVersion)\" />\n  </ItemGroup>\n</Project>\n"
  },
  {
    "path": "build/VSIX.targets",
    "content": "<Project>\n  <PropertyGroup>\n    <!--   Don't build the VSIX by default in this branch anymore. You can still build the fix by adding /p:BuildVSIX=true.   -->\n    <BuildVSIX Condition=\"'$(BuildVSIX)' ==''\">false</BuildVSIX>\n    <RestoreDependsOn Condition=\"'$(OS)'=='Windows_NT' AND '$(BuildVSIX)' == 'true'\">$(RestoreDependsOn);RestoreVSIX</RestoreDependsOn>\n    <PackageDependsOn Condition=\"'$(OS)'=='Windows_NT' AND '$(BuildVSIX)' == 'true'\">$(PackageDependsOn);PackageVSIX</PackageDependsOn>\n    <GetArtifactInfoDependsOn Condition=\"'$(OS)'=='Windows_NT' AND '$(BuildVSIX)' == 'true'\">$(GetArtifactInfoDependsOn);GetVSIXArtifactInfo</GetArtifactInfoDependsOn>\n    <VSIXName>Microsoft.VisualStudio.SecretManager</VSIXName>\n    <VSIXProject>$(RepositoryRoot)tooling\\$(VSIXName)\\$(VSIXName).csproj</VSIXProject>\n    <VSIXOutputPath>$(BuildDir)$(VSIXName).vsix</VSIXOutputPath>\n    <VSIXManifestOutputPath>$(BuildDir)$(VSIXName).json</VSIXManifestOutputPath>\n    <VSIXSymbolsOutputPath>$(BuildDir)$(VSIXName).pdb</VSIXSymbolsOutputPath>\n    <VSIXArtifactCategory>shipoob</VSIXArtifactCategory>\n  </PropertyGroup>\n\n  <Target\n    Name=\"GenerateVSIX\"\n    DependsOnTargets=\"RestoreVSIX;PackageVSIX\"\n    Condition=\"'$(OS)'=='Windows_NT'\" />\n\n  <Target Name=\"GetVSIXArtifactInfo\">\n    <ItemGroup>\n      <ArtifactInfo Include=\"$(VSIXOutputPath)\">\n        <ArtifactType>VsixPackage</ArtifactType>\n        <Version>$(PackageVersion)</Version>\n        <Category>$(VSIXArtifactCategory)</Category>\n        <PackageId>$(VSIXName)</PackageId>\n      </ArtifactInfo>\n\n      <ArtifactInfo Include=\"$(VSIXManifestOutputPath)\">\n        <ArtifactType>VsixPackageManifestFile</ArtifactType>\n        <Category>$(VSIXArtifactCategory)</Category>\n        <Dependencies>$(VSIXName).vsix</Dependencies>\n        <PackageId>$(VSIXName)</PackageId>\n      </ArtifactInfo>\n\n      <ArtifactInfo Include=\"$(VSIXSymbolsOutputPath)\">\n        <ArtifactType>SymbolsFile</ArtifactType>\n        <Category>$(VSIXArtifactCategory)</Category>\n        <Dependencies>$(VSIXName).vsix</Dependencies>\n        <DebugType>full</DebugType>\n      </ArtifactInfo>\n\n      <FilesToSign Include=\"$(VSIXOutputPath)\" Certificate=\"$(VsixSigningCertName)\" IsContainer=\"true\" />\n      <FilesToSign Include=\"$(RepositoryRoot)tooling/Microsoft.VisualStudio.SecretManager/bin/$(Configuration)/Microsoft.VisualStudio.SecretManager.dll\" Certificate=\"$(AssemblySigningCertName)\" />\n      <FilesToExcludeFromSigning Include=\"$(VSIXManifestOutputPath)\" />\n      <FilesToExcludeFromSigning Include=\"$(VSIXSymbolsOutputPath)\" />\n    </ItemGroup>\n  </Target>\n\n  <!--\n    VisualStudioMSBuildx86Path is set by the GetToolsets target in KoreBuild if a version of VS matching the requirements in korebuild.json is found.\n   -->\n  <Target Name=\"RestoreVSIX\" DependsOnTargets=\"GetToolsets\">\n\n    <PropertyGroup>\n      <VSIXResponseFilePath>$(LogOutputDir)vsix-restore.rsp</VSIXResponseFilePath>\n    </PropertyGroup>\n\n    <ItemGroup>\n      <MSBuildArguments Remove=\"@(MSBuildArguments)\" />\n      <MSBuildArguments Include=\"\n        $(VSIXProject);\n        /t:Restore;\n        /m;\n        /v:m;\n        /p:Configuration=$(Configuration);\n        /p:BuildNumber=$(BuildNumber);\n        /p:PackageReferencePropsPath=$(MSBuildThisFileDirectory)VSIX.props;\" />\n      <MSBuildArguments Include=\"/p:DotNetPackageVersionPropsPath=$(DotNetPackageVersionPropsPath)\" Condition=\"'$(DotNetPackageVersionPropsPath)' != ''\" />\n      <MSBuildArguments Include=\"/p:DotNetRestoreSourcePropsPath=$(DotNetRestoreSourcePropsPath)\" Condition=\"'$(DotNetRestoreSourcePropsPath)' != ''\" />\n    </ItemGroup>\n\n    <MakeDir Directories=\"$(LogOutputDir)\" />\n\n    <WriteLinesToFile\n      File=\"$(VSIXResponseFilePath)\"\n      Lines=\"@(MSBuildArguments)\"\n      Overwrite=\"true\" />\n\n    <Exec Command=\"&quot;$(VisualStudioMSBuildx86Path)&quot; @&quot;$(VSIXResponseFilePath)&quot;\"\n      Condition=\"'$(VisualStudioMSBuildx86Path)' != ''\" />\n  </Target>\n\n  <Target Name=\"PackageVSIX\" DependsOnTargets=\"GetToolsets\">\n\n    <Error Text=\"Could not find a version of Visual Studio that has the Visual Studio SDK installed. This is required to build the SecretManager VSIX.\"\n      Condition=\"'$(VisualStudioMSBuildx86Path)' == ''\" />\n\n    <PropertyGroup>\n      <VSIXLogFilePath>$(LogOutputDir)vsix.log</VSIXLogFilePath>\n      <VSIXResponseFilePath>$(LogOutputDir)vsix-build.rsp</VSIXResponseFilePath>\n    </PropertyGroup>\n\n    <ItemGroup>\n      <MSBuildArguments Remove=\"@(MSBuildArguments)\" />\n      <MSBuildArguments Include=\"\n        $(VSIXProject);\n        /m;\n        /v:M;\n        /fl;\n        /flp:LogFile=$(VSIXLogFilePath);\n        /p:DeployExtension=false;\n        /p:TargetVSIXContainer=$(VSIXOutputPath);\n        /p:Configuration=$(Configuration);\n        /p:SymbolsPublishDir=$(BuildDir);\n        /p:PackageReferencePropsPath=$(MSBuildThisFileDirectory)VSIX.props;\" />\n    </ItemGroup>\n\n    <MakeDir Directories=\"$(LogOutputDir)\" />\n\n    <WriteLinesToFile\n      File=\"$(VSIXResponseFilePath)\"\n      Lines=\"@(MSBuildArguments)\"\n      Overwrite=\"true\" />\n\n    <Exec Command=\"&quot;$(VisualStudioMSBuildx86Path)&quot; @&quot;$(VSIXResponseFilePath)&quot;\"\n      Condition=\"'$(VisualStudioMSBuildx86Path)' != ''\" />\n  </Target>\n\n</Project>\n"
  },
  {
    "path": "build/dependencies.props",
    "content": "﻿<Project>\n  <PropertyGroup>\n    <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>\n  </PropertyGroup>\n  <PropertyGroup Label=\"Package Versions\">\n    <InternalAspNetCoreSdkPackageVersion>3.0.0-alpha1-20181026.5</InternalAspNetCoreSdkPackageVersion>\n    <MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>3.0.0-alpha1-10657</MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>\n    <MicrosoftAspNetCoreTestingPackageVersion>3.0.0-alpha1-10657</MicrosoftAspNetCoreTestingPackageVersion>\n    <MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>3.0.0-alpha1-10657</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>\n    <MicrosoftExtensionsConfigurationUserSecretsPackageVersion>3.0.0-alpha1-10664</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>\n    <MicrosoftExtensionsProcessSourcesPackageVersion>3.0.0-alpha1-10657</MicrosoftExtensionsProcessSourcesPackageVersion>\n    <MicrosoftNETCoreApp30PackageVersion>3.0.0-preview1-26907-05</MicrosoftNETCoreApp30PackageVersion>\n    <MicrosoftNETTestSdkPackageVersion>15.9.0</MicrosoftNETTestSdkPackageVersion>\n    <MicrosoftWebApiClientPackageVersion>5.2.6</MicrosoftWebApiClientPackageVersion>\n    <NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>\n    <NewtonsoftJsonPackageVersion>11.0.2</NewtonsoftJsonPackageVersion>\n    <SystemDataSqlClientPackageVersion>4.6.0-preview1-26907-04</SystemDataSqlClientPackageVersion>\n    <SystemSecurityCryptographyCngPackageVersion>4.6.0-preview1-26907-04</SystemSecurityCryptographyCngPackageVersion>\n    <VisualStudio_NewtonsoftJsonPackageVersion>9.0.1</VisualStudio_NewtonsoftJsonPackageVersion>\n    <XunitPackageVersion>2.4.0</XunitPackageVersion>\n    <XunitRunnerVisualStudioPackageVersion>2.4.0</XunitRunnerVisualStudioPackageVersion>\n  </PropertyGroup>\n  <Import Project=\"$(DotNetPackageVersionPropsPath)\" Condition=\" '$(DotNetPackageVersionPropsPath)' != '' \" />\n  <PropertyGroup Label=\"Package Versions: Pinned\" />\n</Project>\n"
  },
  {
    "path": "build/repo.props",
    "content": "<Project>\n  <Import Project=\"dependencies.props\" />\n\n  <ItemGroup>\n    <DotNetCoreRuntime Include=\"$(MicrosoftNETCoreApp30PackageVersion)\" />\n  </ItemGroup>\n\n  <PropertyGroup>\n    <!-- These properties are use by the automation that updates dependencies.props -->\n    <LineupPackageId>Internal.AspNetCore.Universe.Lineup</LineupPackageId>\n    <LineupPackageRestoreSource>https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json</LineupPackageRestoreSource>\n  </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "build/repo.targets",
    "content": "<Project>\n  <Import Project=\"VSIX.targets\" />\n\n  <ItemGroup>\n    <Solutions Update=\"$(RepositoryRoot)DotNetTools.sln\">\n      <!-- the 'DebugNoVSIX' and 'ReleaseNoVSIX' configurations exclude the VSIX project, which doesn't build with Microsoft.NET.Sdk yet. -->\n      <AdditionalProperties>Configuration=$(Configuration)NoVSIX</AdditionalProperties>\n    </Solutions>\n  </ItemGroup>\n</Project>\n"
  },
  {
    "path": "build/sources.props",
    "content": "<Project>\n  <Import Project=\"$(DotNetRestoreSourcePropsPath)\" Condition=\"'$(DotNetRestoreSourcePropsPath)' != ''\"/>\n\n  <PropertyGroup Label=\"RestoreSources\">\n    <RestoreSources>$(DotNetRestoreSources)</RestoreSources>\n    <RestoreSources Condition=\"'$(DotNetBuildOffline)' != 'true' AND '$(AspNetUniverseBuildOffline)' != 'true' \">\n      $(RestoreSources);\n      https://dotnet.myget.org/F/dotnet-core/api/v3/index.json;\n      https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json;\n      https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;\n      https://vside.myget.org/F/vssdk/api/v3/index.json;\n      https://vside.myget.org/F/devcore/api/v3/index.json\n    </RestoreSources>\n    <RestoreSources Condition=\"'$(DotNetBuildOffline)' != 'true'\">\n      $(RestoreSources);\n      https://api.nuget.org/v3/index.json;\n    </RestoreSources>\n  </PropertyGroup>\n</Project>\n"
  },
  {
    "path": "build.cmd",
    "content": "@ECHO OFF\nPowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command \"[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE\"\n"
  },
  {
    "path": "build.sh",
    "content": "#!/usr/bin/env bash\n\nset -euo pipefail\nDIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\n# Call \"sync\" between \"chmod\" and execution to prevent \"text file busy\" error in Docker (aufs)\nchmod +x \"$DIR/run.sh\"; sync\n\"$DIR/run.sh\" default-build \"$@\"\n"
  },
  {
    "path": "korebuild-lock.txt",
    "content": "version:3.0.0-alpha1-20181026.5\r\ncommithash:0c0410ef8b17d5177a05b50cb66f9ad89ce15e32\r\n"
  },
  {
    "path": "korebuild.json",
    "content": "{\n  \"$schema\": \"https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json\",\n  \"channel\": \"master\",\n  \"toolsets\": {\n    \"visualstudio\": {\n      \"required\": [\n        \"windows\"\n      ],\n      \"includePrerelease\": true,\n      \"versionRange\": \"[15.0.26730.03, 16.0)\",\n      \"requiredWorkloads\": [\n        \"Microsoft.VisualStudio.Component.VSSDK\"\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "run.cmd",
    "content": "@ECHO OFF\nPowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command \"[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE\"\n"
  },
  {
    "path": "run.ps1",
    "content": "#!/usr/bin/env powershell\n#requires -version 4\n\n<#\n.SYNOPSIS\nExecutes KoreBuild commands.\n\n.DESCRIPTION\nDownloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`.\n\n.PARAMETER Command\nThe KoreBuild command to run.\n\n.PARAMETER Path\nThe folder to build. Defaults to the folder containing this script.\n\n.PARAMETER Channel\nThe channel of KoreBuild to download. Overrides the value from the config file.\n\n.PARAMETER DotNetHome\nThe directory where .NET Core tools will be stored.\n\n.PARAMETER ToolsSource\nThe base url where build tools can be downloaded. Overrides the value from the config file.\n\n.PARAMETER Update\nUpdates KoreBuild to the latest version even if a lock file is present.\n\n.PARAMETER Reinstall\nRe-installs KoreBuild\n\n.PARAMETER ConfigFile\nThe path to the configuration file that stores values. Defaults to korebuild.json.\n\n.PARAMETER ToolsSourceSuffix\nThe Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores.\n\n.PARAMETER CI\nSets up CI specific settings and variables.\n\n.PARAMETER Arguments\nArguments to be passed to the command\n\n.NOTES\nThis function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be.\nWhen the lockfile is not present, KoreBuild will create one using latest available version from $Channel.\n\nThe $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set\nin the file are overridden by command line parameters.\n\n.EXAMPLE\nExample config file:\n```json\n{\n  \"$schema\": \"https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json\",\n  \"channel\": \"master\",\n  \"toolsSource\": \"https://aspnetcore.blob.core.windows.net/buildtools\"\n}\n```\n#>\n[CmdletBinding(PositionalBinding = $false)]\nparam(\n    [Parameter(Mandatory = $true, Position = 0)]\n    [string]$Command,\n    [string]$Path = $PSScriptRoot,\n    [Alias('c')]\n    [string]$Channel,\n    [Alias('d')]\n    [string]$DotNetHome,\n    [Alias('s')]\n    [string]$ToolsSource,\n    [Alias('u')]\n    [switch]$Update,\n    [switch]$Reinstall,\n    [string]$ToolsSourceSuffix,\n    [string]$ConfigFile = $null,\n    [switch]$CI,\n    [Parameter(ValueFromRemainingArguments = $true)]\n    [string[]]$Arguments\n)\n\nSet-StrictMode -Version 2\n$ErrorActionPreference = 'Stop'\n\n#\n# Functions\n#\n\nfunction Get-KoreBuild {\n\n    $lockFile = Join-Path $Path 'korebuild-lock.txt'\n\n    if (!(Test-Path $lockFile) -or $Update) {\n        Get-RemoteFile \"$ToolsSource/korebuild/channels/$Channel/latest.txt\" $lockFile $ToolsSourceSuffix\n    }\n\n    $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1\n    if (!$version) {\n        Write-Error \"Failed to parse version from $lockFile. Expected a line that begins with 'version:'\"\n    }\n    $version = $version.TrimStart('version:').Trim()\n    $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version)\n\n    if ($Reinstall -and (Test-Path $korebuildPath)) {\n        Remove-Item -Force -Recurse $korebuildPath\n    }\n\n    if (!(Test-Path $korebuildPath)) {\n        Write-Host -ForegroundColor Magenta \"Downloading KoreBuild $version\"\n        New-Item -ItemType Directory -Path $korebuildPath | Out-Null\n        $remotePath = \"$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip\"\n\n        try {\n            $tmpfile = Join-Path ([IO.Path]::GetTempPath()) \"KoreBuild-$([guid]::NewGuid()).zip\"\n            Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix\n            if (Get-Command -Name 'Microsoft.PowerShell.Archive\\Expand-Archive' -ErrorAction Ignore) {\n                # Use built-in commands where possible as they are cross-plat compatible\n                Microsoft.PowerShell.Archive\\Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath\n            }\n            else {\n                # Fallback to old approach for old installations of PowerShell\n                Add-Type -AssemblyName System.IO.Compression.FileSystem\n                [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath)\n            }\n        }\n        catch {\n            Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore\n            throw\n        }\n        finally {\n            Remove-Item $tmpfile -ErrorAction Ignore\n        }\n    }\n\n    return $korebuildPath\n}\n\nfunction Join-Paths([string]$path, [string[]]$childPaths) {\n    $childPaths | ForEach-Object { $path = Join-Path $path $_ }\n    return $path\n}\n\nfunction Get-RemoteFile([string]$RemotePath, [string]$LocalPath, [string]$RemoteSuffix) {\n    if ($RemotePath -notlike 'http*') {\n        Copy-Item $RemotePath $LocalPath\n        return\n    }\n\n    $retries = 10\n    while ($retries -gt 0) {\n        $retries -= 1\n        try {\n            Invoke-WebRequest -UseBasicParsing -Uri $($RemotePath + $RemoteSuffix) -OutFile $LocalPath\n            return\n        }\n        catch {\n            Write-Verbose \"Request failed. $retries retries remaining\"\n        }\n    }\n\n    Write-Error \"Download failed: '$RemotePath'.\"\n}\n\n#\n# Main\n#\n\n# Load configuration or set defaults\n\n$Path = Resolve-Path $Path\nif (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' }\n\nif (Test-Path $ConfigFile) {\n    try {\n        $config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json\n        if ($config) {\n            if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel }\n            if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource}\n        }\n    }\n    catch {\n        Write-Host -ForegroundColor Red $Error[0]\n        Write-Error \"$ConfigFile contains invalid JSON.\"\n        exit 1\n    }\n}\n\nif (!$DotNetHome) {\n    $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } `\n        elseif ($CI) { Join-Path $PSScriptRoot '.dotnet' } `\n        elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} `\n        elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}`\n        else { Join-Path $PSScriptRoot '.dotnet'}\n}\n\nif (!$Channel) { $Channel = 'master' }\nif (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' }\n\n# Execute\n\n$korebuildPath = Get-KoreBuild\nImport-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1')\n\ntry {\n    Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile -CI:$CI\n    Invoke-KoreBuildCommand $Command @Arguments\n}\nfinally {\n    Remove-Module 'KoreBuild' -ErrorAction Ignore\n}\n"
  },
  {
    "path": "run.sh",
    "content": "#!/usr/bin/env bash\n\nset -euo pipefail\n\n#\n# variables\n#\n\nRESET=\"\\033[0m\"\nRED=\"\\033[0;31m\"\nYELLOW=\"\\033[0;33m\"\nMAGENTA=\"\\033[0;95m\"\nDIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\nverbose=false\nupdate=false\nreinstall=false\nrepo_path=\"$DIR\"\nchannel=''\ntools_source=''\ntools_source_suffix=''\nci=false\n\n#\n# Functions\n#\n__usage() {\n    echo \"Usage: $(basename \"${BASH_SOURCE[0]}\") command [options] [[--] <Arguments>...]\"\n    echo \"\"\n    echo \"Arguments:\"\n    echo \"    command                The command to be run.\"\n    echo \"    <Arguments>...         Arguments passed to the command. Variable number of arguments allowed.\"\n    echo \"\"\n    echo \"Options:\"\n    echo \"    --verbose                                             Show verbose output.\"\n    echo \"    -c|--channel <CHANNEL>                                The channel of KoreBuild to download. Overrides the value from the config file..\"\n    echo \"    --config-file <FILE>                                  The path to the configuration file that stores values. Defaults to korebuild.json.\"\n    echo \"    -d|--dotnet-home <DIR>                                The directory where .NET Core tools will be stored. Defaults to '\\$DOTNET_HOME' or '\\$HOME/.dotnet.\"\n    echo \"    --path <PATH>                                         The directory to build. Defaults to the directory containing the script.\"\n    echo \"    -s|--tools-source|-ToolsSource <URL>                  The base url where build tools can be downloaded. Overrides the value from the config file.\"\n    echo \"    --tools-source-suffix|-ToolsSourceSuffix <SUFFIX>     The suffix to append to tools-source. Useful for query strings.\"\n    echo \"    -u|--update                                           Update to the latest KoreBuild even if the lock file is present.\"\n    echo \"    --reinstall                                           Reinstall KoreBuild.\"\n    echo \"    --ci                                                  Apply CI specific settings and environment variables.\"\n    echo \"\"\n    echo \"Description:\"\n    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.\"\n    echo \"    When the lockfile is not present, KoreBuild will create one using latest available version from \\$channel.\"\n\n    if [[ \"${1:-}\" != '--no-exit' ]]; then\n        exit 2\n    fi\n}\n\nget_korebuild() {\n    local version\n    local lock_file=\"$repo_path/korebuild-lock.txt\"\n    if [ ! -f \"$lock_file\" ] || [ \"$update\" = true ]; then\n        __get_remote_file \"$tools_source/korebuild/channels/$channel/latest.txt\" \"$lock_file\" \"$tools_source_suffix\"\n    fi\n    version=\"$(grep 'version:*' -m 1 \"$lock_file\")\"\n    if [[ \"$version\" == '' ]]; then\n        __error \"Failed to parse version from $lock_file. Expected a line that begins with 'version:'\"\n        return 1\n    fi\n    version=\"$(echo \"${version#version:}\" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')\"\n    local korebuild_path=\"$DOTNET_HOME/buildtools/korebuild/$version\"\n\n    if [ \"$reinstall\" = true ] && [ -d \"$korebuild_path\" ]; then\n        rm -rf \"$korebuild_path\"\n    fi\n\n    {\n        if [ ! -d \"$korebuild_path\" ]; then\n            mkdir -p \"$korebuild_path\"\n            local remote_path=\"$tools_source/korebuild/artifacts/$version/korebuild.$version.zip\"\n            tmpfile=\"$(mktemp)\"\n            echo -e \"${MAGENTA}Downloading KoreBuild ${version}${RESET}\"\n            if __get_remote_file \"$remote_path\" \"$tmpfile\" \"$tools_source_suffix\"; then\n                unzip -q -d \"$korebuild_path\" \"$tmpfile\"\n            fi\n            rm \"$tmpfile\" || true\n        fi\n\n        source \"$korebuild_path/KoreBuild.sh\"\n    } || {\n        if [ -d \"$korebuild_path\" ]; then\n            echo \"Cleaning up after failed installation\"\n            rm -rf \"$korebuild_path\" || true\n        fi\n        return 1\n    }\n}\n\n__error() {\n    echo -e \"${RED}error: $*${RESET}\" 1>&2\n}\n\n__warn() {\n    echo -e \"${YELLOW}warning: $*${RESET}\"\n}\n\n__machine_has() {\n    hash \"$1\" > /dev/null 2>&1\n    return $?\n}\n\n__get_remote_file() {\n    local remote_path=$1\n    local local_path=$2\n    local remote_path_suffix=$3\n\n    if [[ \"$remote_path\" != 'http'* ]]; then\n        cp \"$remote_path\" \"$local_path\"\n        return 0\n    fi\n\n    local failed=false\n    if __machine_has wget; then\n        wget --tries 10 --quiet -O \"$local_path\" \"${remote_path}${remote_path_suffix}\" || failed=true\n    else\n        failed=true\n    fi\n\n    if [ \"$failed\" = true ] && __machine_has curl; then\n        failed=false\n        curl --retry 10 -sSL -f --create-dirs -o \"$local_path\" \"${remote_path}${remote_path_suffix}\" || failed=true\n    fi\n\n    if [ \"$failed\" = true ]; then\n        __error \"Download failed: $remote_path\" 1>&2\n        return 1\n    fi\n}\n\n#\n# main\n#\n\ncommand=\"${1:-}\"\nshift\n\nwhile [[ $# -gt 0 ]]; do\n    case $1 in\n        -\\?|-h|--help)\n            __usage --no-exit\n            exit 0\n            ;;\n        -c|--channel|-Channel)\n            shift\n            channel=\"${1:-}\"\n            [ -z \"$channel\" ] && __usage\n            ;;\n        --config-file|-ConfigFile)\n            shift\n            config_file=\"${1:-}\"\n            [ -z \"$config_file\" ] && __usage\n            if [ ! -f \"$config_file\" ]; then\n                __error \"Invalid value for --config-file. $config_file does not exist.\"\n                exit 1\n            fi\n            ;;\n        -d|--dotnet-home|-DotNetHome)\n            shift\n            DOTNET_HOME=\"${1:-}\"\n            [ -z \"$DOTNET_HOME\" ] && __usage\n            ;;\n        --path|-Path)\n            shift\n            repo_path=\"${1:-}\"\n            [ -z \"$repo_path\" ] && __usage\n            ;;\n        -s|--tools-source|-ToolsSource)\n            shift\n            tools_source=\"${1:-}\"\n            [ -z \"$tools_source\" ] && __usage\n            ;;\n        --tools-source-suffix|-ToolsSourceSuffix)\n            shift\n            tools_source_suffix=\"${1:-}\"\n            [ -z \"$tools_source_suffix\" ] && __usage\n            ;;\n        -u|--update|-Update)\n            update=true\n            ;;\n        --reinstall|-[Rr]einstall)\n            reinstall=true\n            ;;\n        --ci|-[Cc][Ii])\n            ci=true\n            if [[ -z \"${DOTNET_HOME:-}\" ]]; then\n                DOTNET_HOME=\"$DIR/.dotnet\"\n            fi\n            ;;\n        --verbose|-Verbose)\n            verbose=true\n            ;;\n        --)\n            shift\n            break\n            ;;\n        *)\n            break\n            ;;\n    esac\n    shift\ndone\n\nif ! __machine_has unzip; then\n    __error 'Missing required command: unzip'\n    exit 1\nfi\n\nif ! __machine_has curl && ! __machine_has wget; then\n    __error 'Missing required command. Either wget or curl is required.'\n    exit 1\nfi\n\n[ -z \"${config_file:-}\" ] && config_file=\"$repo_path/korebuild.json\"\nif [ -f \"$config_file\" ]; then\n    if __machine_has jq ; then\n        if jq '.' \"$config_file\" >/dev/null ; then\n            config_channel=\"$(jq -r 'select(.channel!=null) | .channel' \"$config_file\")\"\n            config_tools_source=\"$(jq -r 'select(.toolsSource!=null) | .toolsSource' \"$config_file\")\"\n        else\n            __error \"$config_file contains invalid JSON.\"\n            exit 1\n        fi\n    elif __machine_has python ; then\n        if python -c \"import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))\" >/dev/null ; then\n            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 '')\")\"\n            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 '')\")\"\n        else\n            __error \"$config_file contains invalid JSON.\"\n            exit 1\n        fi\n    elif __machine_has python3 ; then\n        if python3 -c \"import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))\" >/dev/null ; then\n            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 '')\")\"\n            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 '')\")\"\n        else\n            __error \"$config_file contains invalid JSON.\"\n            exit 1\n        fi\n    else\n        __error 'Missing required command: jq or python. Could not parse the JSON file.'\n        exit 1\n    fi\n\n    [ ! -z \"${config_channel:-}\" ] && channel=\"$config_channel\"\n    [ ! -z \"${config_tools_source:-}\" ] && tools_source=\"$config_tools_source\"\nfi\n\n[ -z \"${DOTNET_HOME:-}\" ] && DOTNET_HOME=\"$HOME/.dotnet\"\n[ -z \"$channel\" ] && channel='master'\n[ -z \"$tools_source\" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools'\n\nget_korebuild\nset_korebuildsettings \"$tools_source\" \"$DOTNET_HOME\" \"$repo_path\" \"$config_file\" \"$ci\"\ninvoke_korebuild_command \"$command\" \"$@\"\n"
  },
  {
    "path": "samples/dotnet-watch/Directory.Build.props",
    "content": "<!-- Intentionally empty to isolate the samples. -->\n<Project />\n"
  },
  {
    "path": "samples/dotnet-watch/Directory.Build.targets",
    "content": "<!-- Intentionally empty to isolate the samples. -->\n<Project />\n"
  },
  {
    "path": "samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Watch Include=\"say-hello.js\" />\n  </ItemGroup>\n\n  <Target Name=\"RunMyNpmCommand\">\n    <Exec Command=\"npm run custom\" />\n  </Target>\n</Project>\n"
  },
  {
    "path": "samples/dotnet-watch/LaunchAnyCommand/README.md",
    "content": "Launch any command with dotnet-watch\n====================================\n\n## Prerequisites\n\n1. Install .NET Core command line. <https://dot.net/core>\n2. Install NodeJS. <https://nodejs.org>\n\n## Usage\n\nOpen a terminal to the directory containing this project.\n\n```\ndotnet watch msbuild /t:RunMyNpmCommand\n```\n\nChanging the .csproj file, or the say-hello.js file will cause dotnet-watch to re-run the 'RunMyNpmCommand' target in MyApp.csproj.\n"
  },
  {
    "path": "samples/dotnet-watch/LaunchAnyCommand/package.json",
    "content": "{\n  \"name\": \"any-command\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"custom\": \"node say-hello.js\"\n  }\n}\n"
  },
  {
    "path": "samples/dotnet-watch/LaunchAnyCommand/say-hello.js",
    "content": "console.log(\"Hello from Javascript\");\n"
  },
  {
    "path": "samples/dotnet-watch/README.md",
    "content": "dotnet-watch samples\n====================\n\nThe samples in this folder show some ways to customize dotnet-watch. For full details on\navailable settings and configuration, see the [README for the dotnet-watch](../../src/dotnet-watch/README.md) project.\n"
  },
  {
    "path": "samples/dotnet-watch/WatchJavascriptFiles/Program.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.IO;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\n\nnamespace WatchJavascriptFiles\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel()\n                .UseContentRoot(Directory.GetCurrentDirectory())\n                .Configure(app =>\n                    app.Run(async (context) =>\n                    {\n                        await context.Response.WriteAsync(\"Hello World!\");\n                    }))\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "samples/dotnet-watch/WatchJavascriptFiles/README.md",
    "content": "Watch JavaScript files with dotnet-watch\n========================================\n\n## Prerequisites\n\nInstall .NET Core command line. <https://dot.net/core>\n\n## Usage\n\nOpen a terminal to the directory containing this project.\n\n```\ndotnet watch run\n```\n\nChanging the .csproj file, or \\*.js file in wwwroot, or any \\*.cs file will cause dotnet-watch to restart the website.\n"
  },
  {
    "path": "samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Folder Include=\"wwwroot\\\" />\n    <Watch Include=\"wwwroot\\**\\*.js\" Exclude=\"wwwroot\\node_modules\\**\\*.js\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore\" Version=\"2.0.0\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/dotnet-watch/WatchJavascriptFiles/wwwroot/app.js",
    "content": "document.title = \"My awesome website\";\n"
  },
  {
    "path": "samples/dotnet-watch/WatchMultipleProjects/README.md",
    "content": "Watch multiple projects with dotnet-watch\n=========================================\n\n## Prerequisites\n\nInstall .NET Core command line. <https://dot.net/core>\n\n## Usage\n\nOpen a terminal to the directory containing this project.\n\n```\ndotnet watch msbuild /t:TestAndRun\n```\n\nThe \"TestAndRun\" target in watch.proj will execute \"dotnet test\" on Test.csproj and then launch the website by calling \"dotnet run\" on Web.csproj.\n\nChanging 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.\n"
  },
  {
    "path": "samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.NET.Test.Sdk\" Version=\"15.0.0\" />\n    <PackageReference Include=\"xunit\" Version=\"2.2.0\" />\n    <PackageReference Include=\"xunit.runner.visualstudio\" Version=\"2.2.0\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/dotnet-watch/WatchMultipleProjects/Test/UnitTest1.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Xunit;\n\nnamespace Test\n{\n    public class UnitTest1\n    {\n        [Fact]\n        public void Test1()\n        {\n            Assert.True(true);\n        }\n    }\n}\n"
  },
  {
    "path": "samples/dotnet-watch/WatchMultipleProjects/Web/Program.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.IO;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\n\nnamespace Web\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel()\n                .UseContentRoot(Directory.GetCurrentDirectory())\n                .Configure(app =>\n                    app.Run(async (context) =>\n                    {\n                        await context.Response.WriteAsync(\"Hello World!\");\n                    }))\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Folder Include=\"wwwroot\\\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore\" Version=\"1.1.1\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/dotnet-watch/WatchMultipleProjects/watch.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n    <EnableDefaultItems>false</EnableDefaultItems>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"Web\\Web.csproj\" />\n    <ProjectReference Include=\"Test\\Test.csproj\" />\n  </ItemGroup>\n\n  <Target Name=\"TestAndRun\">\n    <Exec Command=\"dotnet test\" WorkingDirectory=\"Test/\" />\n    <Exec Command=\"dotnet run\" WorkingDirectory=\"Web/\" />\n  </Target>\n\n</Project>\n"
  },
  {
    "path": "shared/CliContext.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\n\nnamespace Microsoft.Extensions.Tools.Internal\n{\n    public static class CliContext\n    {\n        /// <summary>\n        /// dotnet -d|--diagnostics subcommand\n        /// </summary>\n        /// <returns></returns>\n        public static bool IsGlobalVerbose()\n        {\n            bool.TryParse(Environment.GetEnvironmentVariable(\"DOTNET_CLI_CONTEXT_VERBOSE\"), out bool globalVerbose);\n            return globalVerbose;\n        }\n    }\n}\n"
  },
  {
    "path": "shared/CommandLineApplicationExtensions.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Reflection;\n\nnamespace Microsoft.Extensions.CommandLineUtils\n{\n    internal static class CommandLineApplicationExtensions\n    {\n        public static CommandOption HelpOption(this CommandLineApplication app)\n            => app.HelpOption(\"-?|-h|--help\");\n\n        public static CommandOption VerboseOption(this CommandLineApplication app)\n            => app.Option(\"-v|--verbose\", \"Show verbose output\", CommandOptionType.NoValue, inherited: true);\n\n        public static void OnExecute(this CommandLineApplication app, Action action)\n            => app.OnExecute(() =>\n                {\n                    action();\n                    return 0;\n                });\n\n        public static void VersionOptionFromAssemblyAttributes(this CommandLineApplication app, Assembly assembly)\n            => app.VersionOption(\"--version\", GetInformationalVersion(assembly));\n\n        private static string GetInformationalVersion(Assembly assembly)\n        {\n            var attribute = assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();\n\n            var versionAttribute = attribute == null\n                ? assembly.GetName().Version.ToString()\n                : attribute.InformationalVersion;\n\n            return versionAttribute;\n        }\n    }\n}\n"
  },
  {
    "path": "shared/ConsoleReporter.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\n\nnamespace Microsoft.Extensions.Tools.Internal\n{\n    public class ConsoleReporter : IReporter\n    {\n        private object _writeLock = new object();\n\n        public ConsoleReporter(IConsole console)\n            : this(console, verbose: false, quiet: false)\n        { }\n\n        public ConsoleReporter(IConsole console, bool verbose, bool quiet)\n        {\n            Ensure.NotNull(console, nameof(console));\n\n            Console = console;\n            IsVerbose = verbose;\n            IsQuiet = quiet;\n        }\n\n        protected IConsole Console { get; }\n        public bool IsVerbose { get; set; }\n        public bool IsQuiet { get; set; }\n\n        protected virtual void WriteLine(TextWriter writer, string message, ConsoleColor? color)\n        {\n            lock (_writeLock)\n            {\n                if (color.HasValue)\n                {\n                    Console.ForegroundColor = color.Value;\n                }\n\n                writer.WriteLine(message);\n\n                if (color.HasValue)\n                {\n                    Console.ResetColor();\n                }\n            }\n        }\n\n        public virtual void Error(string message)\n            => WriteLine(Console.Error, message, ConsoleColor.Red);\n        public virtual void Warn(string message)\n            => WriteLine(Console.Out, message, ConsoleColor.Yellow);\n\n        public virtual void Output(string message)\n        {\n            if (IsQuiet)\n            {\n                return;\n            }\n            WriteLine(Console.Out, message, color: null);\n        }\n\n        public virtual void Verbose(string message)\n        {\n            if (!IsVerbose)\n            {\n                return;\n            }\n\n            WriteLine(Console.Out, message, ConsoleColor.DarkGray);\n        }\n    }\n}\n"
  },
  {
    "path": "shared/DebugHelper.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Diagnostics;\nusing System.Linq;\n\nnamespace Microsoft.Extensions.Tools.Internal\n{\n    public static class DebugHelper\n    {\n        [Conditional(\"DEBUG\")]\n        public static void HandleDebugSwitch(ref string[] args)\n        {\n            if (args.Length > 0 && string.Equals(\"--debug\", args[0], StringComparison.OrdinalIgnoreCase))\n            {\n                args = args.Skip(1).ToArray();\n                Console.WriteLine(\"Waiting for debugger to attach. Press ENTER to continue\");\n                Console.WriteLine($\"Process ID: {Process.GetCurrentProcess().Id}\");\n                Console.ReadLine();\n            }\n        }\n    }\n}"
  },
  {
    "path": "shared/Ensure.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\n\nnamespace Microsoft.Extensions.Tools.Internal\n{\n    internal static class Ensure\n    {\n        public static T NotNull<T>(T obj, string paramName)\n            where T : class\n        {\n            if (obj == null)\n            {\n                throw new ArgumentNullException(paramName);\n            }\n            return obj;\n        }\n\n        public static string NotNullOrEmpty(string obj, string paramName)\n        {\n            if (string.IsNullOrEmpty(obj))\n            {\n                throw new ArgumentException(\"Value cannot be null or an empty string.\", paramName);\n            }\n            return obj;\n        }\n    }\n}\n"
  },
  {
    "path": "shared/IConsole.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\n\nnamespace Microsoft.Extensions.Tools.Internal\n{\n    public interface IConsole\n    {\n        event ConsoleCancelEventHandler CancelKeyPress;\n        TextWriter Out { get; }\n        TextWriter Error { get; }\n        TextReader In { get; }\n        bool IsInputRedirected { get; }\n        bool IsOutputRedirected { get; }\n        bool IsErrorRedirected { get; }\n        ConsoleColor ForegroundColor { get; set; }\n        void ResetColor();\n    }\n}\n"
  },
  {
    "path": "shared/IReporter.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.Extensions.Tools.Internal\n{\n    public interface IReporter\n    {\n        void Verbose(string message);\n        void Output(string message);\n        void Warn(string message);\n        void Error(string message);\n    }\n}"
  },
  {
    "path": "shared/NullReporter.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.Extensions.Tools.Internal\n{\n    public class NullReporter : IReporter\n    {\n        private NullReporter()\n        { }\n\n        public static IReporter Singleton { get; } = new NullReporter();\n\n        public void Verbose(string message)\n        { }\n\n        public void Output(string message)\n        { }\n\n        public void Warn(string message)\n        { }\n\n        public void Error(string message)\n        { }\n    }\n}\n"
  },
  {
    "path": "shared/PhysicalConsole.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\n\nnamespace Microsoft.Extensions.Tools.Internal\n{\n    public class PhysicalConsole : IConsole\n    {\n        private PhysicalConsole()\n        {\n            Console.CancelKeyPress += (o, e) =>\n            {\n                CancelKeyPress?.Invoke(o, e);\n            };\n        }\n\n        public static IConsole Singleton { get; } = new PhysicalConsole();\n\n        public event ConsoleCancelEventHandler CancelKeyPress;\n        public TextWriter Error => Console.Error;\n        public TextReader In => Console.In;\n        public TextWriter Out => Console.Out;\n        public bool IsInputRedirected => Console.IsInputRedirected;\n        public bool IsOutputRedirected => Console.IsOutputRedirected;\n        public bool IsErrorRedirected => Console.IsErrorRedirected;\n        public ConsoleColor ForegroundColor\n        {\n            get => Console.ForegroundColor;\n            set => Console.ForegroundColor = value;\n        }\n\n        public void ResetColor() => Console.ResetColor();\n    }\n}\n"
  },
  {
    "path": "src/Directory.Build.props",
    "content": "<Project>\n  <Import Project=\"..\\Directory.Build.props\" />\n\n  <ItemGroup>\n    <PackageReference Include=\"Internal.AspNetCore.Sdk\" PrivateAssets=\"All\" Version=\"$(InternalAspNetCoreSdkPackageVersion)\" />\n  </ItemGroup>\n</Project>\n"
  },
  {
    "path": "src/Directory.Build.targets",
    "content": "<Project>\n  <Import Project=\"..\\Directory.Build.targets\" />\n\n  <Target Name=\"CleanPublishDir\" AfterTargets=\"CoreClean\">\n    <RemoveDir Directories=\"$(PublishDir)\" />\n  </Target>\n</Project>\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/CertificateGenerator.cs",
    "content": "using System;\nusing Microsoft.AspNetCore.Certificates.Generation;\n\nnamespace Microsoft.AspNetCore.DeveloperCertificates.XPlat\n{\n    public static class CertificateGenerator\n    {\n        public static void GenerateAspNetHttpsCertificate()\n        {\n            var manager = new CertificateManager();\n            var now = DateTimeOffset.Now;\n            manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n    <Description>Package for the CLI first run experience.</Description>\n    <DefineConstants>$(DefineConstants);XPLAT</DefineConstants>\n    <PackageTags>aspnet;cli</PackageTags>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Certificates.Generation.Sources\" PrivateAssets=\"All\" Version=\"$(MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/AggregateDirectoryStructure.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Microsoft.HttpRepl\n{\n    public class AggregateDirectoryStructure : IDirectoryStructure\n    {\n        private readonly IDirectoryStructure _first;\n        private readonly IDirectoryStructure _second;\n\n        public AggregateDirectoryStructure(IDirectoryStructure first, IDirectoryStructure second)\n        {\n            _first = first;\n            _second = second;\n        }\n\n        public IEnumerable<string> DirectoryNames\n        {\n            get\n            {\n                HashSet<string> values = new HashSet<string>(StringComparer.OrdinalIgnoreCase);\n                values.UnionWith(_first.DirectoryNames);\n                values.UnionWith(_second.DirectoryNames);\n                return values.OrderBy(x => x, StringComparer.OrdinalIgnoreCase);\n            }\n        }\n\n        public IDirectoryStructure Parent => _first.Parent ?? _second.Parent;\n\n        public IDirectoryStructure GetChildDirectory(string name)\n        {\n            return new AggregateDirectoryStructure(_first.GetChildDirectory(name), _second.GetChildDirectory(name));\n        }\n\n        public IRequestInfo RequestInfo => _first.RequestInfo ?? _second.RequestInfo;\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing System.Net.Http;\nusing System.Net.Http.Headers;\nusing System.Text;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing System.Xml.Linq;\nusing Microsoft.HttpRepl.Formatting;\nusing Microsoft.HttpRepl.Preferences;\nusing Microsoft.HttpRepl.Suggestions;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\nusing Microsoft.Repl.Suggestions;\nusing Newtonsoft.Json.Linq;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public abstract class BaseHttpCommand : CommandWithStructuredInputBase<HttpState, ICoreParseResult>\n    {\n        private const string HeaderOption = nameof(HeaderOption);\n        private const string ResponseHeadersFileOption = nameof(ResponseHeadersFileOption);\n        private const string ResponseBodyFileOption = nameof(ResponseBodyFileOption);\n        private const string ResponseFileOption = nameof(ResponseFileOption);\n        private const string BodyFileOption = nameof(BodyFileOption);\n        private const string NoBodyOption = nameof(NoBodyOption);\n        private const string NoFormattingOption = nameof(NoFormattingOption);\n        private const string StreamingOption = nameof(StreamingOption);\n        private const string BodyContentOption = nameof(BodyContentOption);\n        private static readonly char[] HeaderSeparatorChars = new[] { '=', ':' };\n\n        private CommandInputSpecification _inputSpec;\n\n        protected abstract string Verb { get; }\n\n        protected abstract bool RequiresBody { get; }\n\n        public override CommandInputSpecification InputSpec\n        {\n            get\n            {\n                if (_inputSpec != null)\n                {\n                    return _inputSpec;\n                }\n\n                CommandInputSpecificationBuilder builder = CommandInputSpecification.Create(Verb)\n                    .MaximumArgCount(1)\n                    .WithOption(new CommandOptionSpecification(HeaderOption, requiresValue: true, forms: new[] {\"--header\", \"-h\"}))\n                    .WithOption(new CommandOptionSpecification(ResponseFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { \"--response\", }))\n                    .WithOption(new CommandOptionSpecification(ResponseHeadersFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { \"--response:headers\", }))\n                    .WithOption(new CommandOptionSpecification(ResponseBodyFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { \"--response:body\", }))\n                    .WithOption(new CommandOptionSpecification(NoFormattingOption, maximumOccurrences: 1, forms: new[] { \"--no-formatting\", \"-F\" }))\n                    .WithOption(new CommandOptionSpecification(StreamingOption, maximumOccurrences: 1, forms: new[] { \"--streaming\", \"-s\" }));\n\n                if (RequiresBody)\n                {\n                    builder = builder.WithOption(new CommandOptionSpecification(NoBodyOption, maximumOccurrences: 1, forms: \"--no-body\"))\n                        .WithOption(new CommandOptionSpecification(BodyFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] {\"--file\", \"-f\"}))\n                        .WithOption(new CommandOptionSpecification(BodyContentOption, requiresValue: true, maximumOccurrences: 1, forms: new[] {\"--content\", \"-c\"}));\n                }\n\n                _inputSpec = builder.Finish();\n                return _inputSpec;\n            }\n        }\n\n        protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)\n        {\n            if (programState.BaseAddress == null && (commandInput.Arguments.Count == 0 || !Uri.TryCreate(commandInput.Arguments[0].Text, UriKind.Absolute, out Uri _)))\n            {\n                shellState.ConsoleManager.Error.WriteLine(\"'set base {url}' must be called before issuing requests to a relative path\".SetColor(programState.ErrorColor));\n                return;\n            }\n\n            if (programState.SwaggerEndpoint != null)\n            {\n                string swaggerRequeryBehaviorSetting = programState.GetStringPreference(WellKnownPreference.SwaggerRequeryBehavior, \"auto\");\n\n                if (swaggerRequeryBehaviorSetting.StartsWith(\"auto\", StringComparison.OrdinalIgnoreCase))\n                {\n                    await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, programState, programState.SwaggerEndpoint, cancellationToken).ConfigureAwait(false);\n                }\n            }\n\n            Dictionary<string, string> thisRequestHeaders = new Dictionary<string, string>();\n\n            foreach (InputElement header in commandInput.Options[HeaderOption])\n            {\n                int equalsIndex = header.Text.IndexOfAny(HeaderSeparatorChars);\n\n                if (equalsIndex < 0)\n                {\n                    shellState.ConsoleManager.Error.WriteLine(\"Headers must be formatted as {header}={value} or {header}:{value}\".SetColor(programState.ErrorColor));\n                    return;\n                }\n\n                thisRequestHeaders[header.Text.Substring(0, equalsIndex)] = header.Text.Substring(equalsIndex + 1);\n            }\n\n            Uri effectivePath = programState.GetEffectivePath(commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty);\n            HttpRequestMessage request = new HttpRequestMessage(new HttpMethod(Verb.ToUpperInvariant()), effectivePath);\n            bool noBody = false;\n\n            if (RequiresBody)\n            {\n                string filePath = null;\n                string bodyContent = null;\n                bool deleteFile = false;\n                noBody = commandInput.Options[NoBodyOption].Count > 0;\n\n                if (!thisRequestHeaders.TryGetValue(\"content-type\", out string contentType) && programState.Headers.TryGetValue(\"content-type\", out IEnumerable<string> contentTypes))\n                {\n                    contentType = contentTypes.FirstOrDefault();\n                }\n\n                if (!noBody)\n                {\n                    if (string.IsNullOrEmpty(contentType))\n                    {\n                        contentType = \"application/json\";\n                    }\n\n                    if (commandInput.Options[BodyFileOption].Count > 0)\n                    {\n                        filePath = commandInput.Options[BodyFileOption][0].Text;\n\n                        if (!File.Exists(filePath))\n                        {\n                            shellState.ConsoleManager.Error.WriteLine($\"Content file {filePath} does not exist\".SetColor(programState.ErrorColor));\n                            return;\n                        }\n                    }\n                    else if (commandInput.Options[BodyContentOption].Count > 0)\n                    {\n                        bodyContent = commandInput.Options[BodyContentOption][0].Text;\n                    }\n                    else\n                    {\n                        string defaultEditorCommand = programState.GetStringPreference(WellKnownPreference.DefaultEditorCommand);\n                        if (defaultEditorCommand == null)\n                        {\n                            shellState.ConsoleManager.Error.WriteLine($\"The default editor must be configured using the command `pref set {WellKnownPreference.DefaultEditorCommand} \\\"{{commandline}}\\\"`\".SetColor(programState.ErrorColor));\n                            return;\n                        }\n\n                        deleteFile = true;\n                        filePath = Path.GetTempFileName();\n\n                        string exampleBody = programState.GetExampleBody(commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty, ref contentType, Verb);\n\n                        if (!string.IsNullOrEmpty(exampleBody))\n                        {\n                            File.WriteAllText(filePath, exampleBody);\n                        }\n\n                        string defaultEditorArguments = programState.GetStringPreference(WellKnownPreference.DefaultEditorArguments) ?? \"\";\n                        string original = defaultEditorArguments;\n                        string pathString = $\"\\\"{filePath}\\\"\";\n\n                        defaultEditorArguments = defaultEditorArguments.Replace(\"{filename}\", pathString);\n\n                        if (string.Equals(defaultEditorArguments, original, StringComparison.Ordinal))\n                        {\n                            defaultEditorArguments = (defaultEditorArguments + \" \" + pathString).Trim();\n                        }\n\n                        ProcessStartInfo info = new ProcessStartInfo(defaultEditorCommand, defaultEditorArguments);\n\n                        Process.Start(info)?.WaitForExit();\n                    }\n                }\n\n                if (string.IsNullOrEmpty(contentType))\n                {\n                    contentType = \"application/json\";\n                }\n\n                byte[] data = noBody \n                    ? new byte[0] \n                    : string.IsNullOrEmpty(bodyContent) \n                        ? File.ReadAllBytes(filePath) \n                        : Encoding.UTF8.GetBytes(bodyContent);\n\n                HttpContent content = new ByteArrayContent(data);\n                content.Headers.ContentType = new MediaTypeHeaderValue(contentType);\n                request.Content = content;\n\n                if (deleteFile)\n                {\n                    File.Delete(filePath);\n                }\n\n                foreach (KeyValuePair<string, IEnumerable<string>> header in programState.Headers)\n                {\n                    content.Headers.TryAddWithoutValidation(header.Key, header.Value);\n                }\n\n                foreach (KeyValuePair<string, string> header in thisRequestHeaders)\n                {\n                    content.Headers.TryAddWithoutValidation(header.Key, header.Value);\n                }\n            }\n\n            foreach (KeyValuePair<string, IEnumerable<string>> header in programState.Headers)\n            {\n                request.Headers.TryAddWithoutValidation(header.Key, header.Value);\n            }\n\n            foreach (KeyValuePair<string, string> header in thisRequestHeaders)\n            {\n                request.Headers.TryAddWithoutValidation(header.Key, header.Value);\n            }\n\n            string headersTarget = commandInput.Options[ResponseHeadersFileOption].FirstOrDefault()?.Text ?? commandInput.Options[ResponseFileOption].FirstOrDefault()?.Text;\n            string bodyTarget = commandInput.Options[ResponseBodyFileOption].FirstOrDefault()?.Text ?? commandInput.Options[ResponseFileOption].FirstOrDefault()?.Text;\n\n            HttpResponseMessage response = await programState.Client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);\n            await HandleResponseAsync(programState, commandInput, shellState.ConsoleManager, response, programState.EchoRequest, headersTarget, bodyTarget, cancellationToken).ConfigureAwait(false);\n        }\n\n        private static async Task HandleResponseAsync(HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, IConsoleManager consoleManager, HttpResponseMessage response, bool echoRequest, string headersTargetFile, string bodyTargetFile, CancellationToken cancellationToken)\n        {\n            RequestConfig requestConfig = new RequestConfig(programState);\n            ResponseConfig responseConfig = new ResponseConfig(programState);\n            string protocolInfo;\n\n            if (echoRequest)\n            {\n                string hostString = response.RequestMessage.RequestUri.Scheme + \"://\" + response.RequestMessage.RequestUri.Host + (!response.RequestMessage.RequestUri.IsDefaultPort ? \":\" + response.RequestMessage.RequestUri.Port : \"\");\n                consoleManager.WriteLine($\"Request to {hostString}...\".SetColor(requestConfig.AddressColor));\n                consoleManager.WriteLine();\n\n                string method = response.RequestMessage.Method.ToString().ToUpperInvariant().SetColor(requestConfig.MethodColor);\n                string pathAndQuery = response.RequestMessage.RequestUri.PathAndQuery.SetColor(requestConfig.AddressColor);\n                protocolInfo = $\"{\"HTTP\".SetColor(requestConfig.ProtocolNameColor)}{\"/\".SetColor(requestConfig.ProtocolSeparatorColor)}{response.Version.ToString().SetColor(requestConfig.ProtocolVersionColor)}\";\n\n                consoleManager.WriteLine($\"{method} {pathAndQuery} {protocolInfo}\");\n                IEnumerable<KeyValuePair<string, IEnumerable<string>>> requestHeaders = response.RequestMessage.Headers;\n\n                if (response.RequestMessage.Content != null)\n                {\n                    requestHeaders = requestHeaders.Union(response.RequestMessage.Content.Headers);\n                }\n\n                foreach (KeyValuePair<string, IEnumerable<string>> header in requestHeaders.OrderBy(x => x.Key))\n                {\n                    string headerKey = header.Key.SetColor(requestConfig.HeaderKeyColor);\n                    string headerSep = \":\".SetColor(requestConfig.HeaderSeparatorColor);\n                    string headerValue = string.Join(\";\".SetColor(requestConfig.HeaderValueSeparatorColor), header.Value.Select(x => x.Trim().SetColor(requestConfig.HeaderValueColor)));\n                    consoleManager.WriteLine($\"{headerKey}{headerSep} {headerValue}\");\n                }\n\n                consoleManager.WriteLine();\n\n                if (response.RequestMessage.Content != null)\n                {\n                    using (StreamWriter writer = new StreamWriter(new MemoryStream()))\n                    {\n                        await FormatBodyAsync(commandInput, programState, consoleManager, response.RequestMessage.Content, writer, cancellationToken).ConfigureAwait(false);\n                    }\n                }\n\n                consoleManager.WriteLine();\n                consoleManager.WriteLine($\"Response from {hostString}...\".SetColor(requestConfig.AddressColor));\n                consoleManager.WriteLine();\n            }\n\n            protocolInfo = $\"{\"HTTP\".SetColor(responseConfig.ProtocolNameColor)}{\"/\".SetColor(responseConfig.ProtocolSeparatorColor)}{response.Version.ToString().SetColor(responseConfig.ProtocolVersionColor)}\";\n            string status = ((int)response.StatusCode).ToString().SetColor(responseConfig.StatusCodeColor) + \" \" + response.ReasonPhrase.SetColor(responseConfig.StatusReasonPhraseColor);\n\n            consoleManager.WriteLine($\"{protocolInfo} {status}\");\n\n            IEnumerable<KeyValuePair<string, IEnumerable<string>>> responseHeaders = response.Headers;\n\n            if (response.Content != null)\n            {\n                responseHeaders = responseHeaders.Union(response.Content.Headers);\n            }\n\n            StreamWriter headerFileWriter;\n\n            if (headersTargetFile != null)\n            {\n                headerFileWriter = new StreamWriter(File.Create(headersTargetFile));\n            }\n            else\n            {\n                headerFileWriter = new StreamWriter(new MemoryStream());\n            }\n\n            foreach (KeyValuePair<string, IEnumerable<string>> header in responseHeaders.OrderBy(x => x.Key))\n            {\n                string headerKey = header.Key.SetColor(responseConfig.HeaderKeyColor);\n                string headerSep = \":\".SetColor(responseConfig.HeaderSeparatorColor);\n                string headerValue = string.Join(\";\".SetColor(responseConfig.HeaderValueSeparatorColor), header.Value.Select(x => x.Trim().SetColor(responseConfig.HeaderValueColor)));\n                consoleManager.WriteLine($\"{headerKey}{headerSep} {headerValue}\");\n                headerFileWriter.WriteLine($\"{header.Key}: {string.Join(\";\", header.Value.Select(x => x.Trim()))}\");\n            }\n\n            StreamWriter bodyFileWriter;\n            if (!string.Equals(headersTargetFile, bodyTargetFile, StringComparison.Ordinal))\n            {\n                headerFileWriter.Flush();\n                headerFileWriter.Close();\n                headerFileWriter.Dispose();\n\n                if (bodyTargetFile != null)\n                {\n                    bodyFileWriter = new StreamWriter(File.Create(bodyTargetFile));\n                }\n                else\n                {\n                    bodyFileWriter = new StreamWriter(new MemoryStream());\n                }\n            }\n            else\n            {\n                headerFileWriter.WriteLine();\n                bodyFileWriter = headerFileWriter;\n            }\n\n            consoleManager.WriteLine();\n\n            if (response.Content != null)\n            {\n                await FormatBodyAsync(commandInput, programState, consoleManager, response.Content, bodyFileWriter, cancellationToken).ConfigureAwait(false);\n            }\n\n            bodyFileWriter.Flush();\n            bodyFileWriter.Close();\n            bodyFileWriter.Dispose();\n\n            consoleManager.WriteLine();\n        }\n\n        private static async Task FormatBodyAsync(DefaultCommandInput<ICoreParseResult> commandInput, HttpState programState, IConsoleManager consoleManager, HttpContent content, StreamWriter bodyFileWriter, CancellationToken cancellationToken)\n        {\n            if (commandInput.Options[StreamingOption].Count > 0)\n            {\n                Memory<char> buffer = new Memory<char>(new char[2048]);\n                Stream s = await content.ReadAsStreamAsync().ConfigureAwait(false);\n                StreamReader reader = new StreamReader(s);\n                consoleManager.WriteLine(\"Streaming the response, press any key to stop...\".SetColor(programState.WarningColor));\n\n                while (!cancellationToken.IsCancellationRequested)\n                {\n                    try\n                    {\n                        ValueTask<int> readTask = reader.ReadAsync(buffer, cancellationToken);\n                        if (await WaitForCompletionAsync(readTask, cancellationToken).ConfigureAwait(false))\n                        {\n                            if (readTask.Result == 0)\n                            {\n                                break;\n                            }\n\n                            string str = new string(buffer.Span.Slice(0, readTask.Result));\n                            consoleManager.Write(str);\n                            bodyFileWriter.Write(str);\n                        }\n                        else\n                        {\n                            break;\n                        }\n                    }\n                    catch (OperationCanceledException)\n                    {\n                    }\n                }\n\n                return;\n            }\n\n            string contentType = null;\n            if (content.Headers.TryGetValues(\"Content-Type\", out IEnumerable<string> contentTypeValues))\n            {\n                contentType = contentTypeValues.FirstOrDefault()?.Split(';').FirstOrDefault();\n            }\n\n            contentType = contentType?.ToUpperInvariant() ?? \"text/plain\";\n\n            if (commandInput.Options[NoFormattingOption].Count == 0)\n            {\n                if (contentType.EndsWith(\"/JSON\", StringComparison.OrdinalIgnoreCase)\n                    || contentType.EndsWith(\"-JSON\", StringComparison.OrdinalIgnoreCase)\n                    || contentType.EndsWith(\"+JSON\", StringComparison.OrdinalIgnoreCase)\n                    || contentType.EndsWith(\"/JAVASCRIPT\", StringComparison.OrdinalIgnoreCase)\n                    || contentType.EndsWith(\"-JAVASCRIPT\", StringComparison.OrdinalIgnoreCase)\n                    || contentType.EndsWith(\"+JAVASCRIPT\", StringComparison.OrdinalIgnoreCase))\n                {\n                    if (await FormatJsonAsync(programState, consoleManager, content, bodyFileWriter))\n                    {\n                        return;\n                    }\n                }\n                else if (contentType.EndsWith(\"/HTML\", StringComparison.OrdinalIgnoreCase)\n                    || contentType.EndsWith(\"-HTML\", StringComparison.OrdinalIgnoreCase)\n                    || contentType.EndsWith(\"+HTML\", StringComparison.OrdinalIgnoreCase)\n                    || contentType.EndsWith(\"/XML\", StringComparison.OrdinalIgnoreCase)\n                    || contentType.EndsWith(\"-XML\", StringComparison.OrdinalIgnoreCase)\n                    || contentType.EndsWith(\"+XML\", StringComparison.OrdinalIgnoreCase))\n                {\n                    if (await FormatXmlAsync(consoleManager, content, bodyFileWriter))\n                    {\n                        return;\n                    }\n                }\n            }\n\n            string responseContent = await content.ReadAsStringAsync().ConfigureAwait(false);\n            bodyFileWriter.WriteLine(responseContent);\n            consoleManager.WriteLine(responseContent);\n        }\n\n        private static async Task<bool> WaitForCompletionAsync(ValueTask<int> readTask, CancellationToken cancellationToken)\n        {\n            while (!readTask.IsCompleted && !cancellationToken.IsCancellationRequested && !Console.KeyAvailable)\n            {\n                await Task.Delay(1, cancellationToken).ConfigureAwait(false);\n            }\n\n            if (Console.KeyAvailable)\n            {\n                Console.ReadKey(false);\n                return false;\n            }\n\n            return readTask.IsCompleted;\n        }\n\n        private static async Task<bool> FormatXmlAsync(IWritable consoleManager, HttpContent content, StreamWriter bodyFileWriter)\n        {\n            string responseContent = await content.ReadAsStringAsync().ConfigureAwait(false);\n            try\n            {\n                XDocument body = XDocument.Parse(responseContent);\n                consoleManager.WriteLine(body.ToString());\n                bodyFileWriter.WriteLine(body.ToString());\n                return true;\n            }\n            catch\n            {\n            }\n\n            return false;\n        }\n\n        private static async Task<bool> FormatJsonAsync(HttpState programState, IWritable outputSink, HttpContent content, StreamWriter bodyFileWriter)\n        {\n            string responseContent = await content.ReadAsStringAsync().ConfigureAwait(false);\n\n            try\n            {\n                JsonConfig config = new JsonConfig(programState);\n                string formatted = JsonVisitor.FormatAndColorize(config, responseContent);\n                outputSink.WriteLine(formatted);\n                bodyFileWriter.WriteLine(JToken.Parse(responseContent).ToString());\n                return true;\n            }\n            catch\n            {\n            }\n\n            return false;\n        }\n\n        protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)\n        {\n            var helpText = new StringBuilder();\n            helpText.Append(\"Usage: \".Bold());\n            helpText.AppendLine($\"{Verb.ToUpperInvariant()} [Options]\");\n            helpText.AppendLine();\n            helpText.AppendLine($\"Issues a {Verb.ToUpperInvariant()} request.\");\n\n            if (RequiresBody)\n            {\n                helpText.AppendLine(\"Your default editor will be opened with a sample body if no options are provided.\");\n            }\n\n            return helpText.ToString();\n        }\n\n        public override string GetHelpSummary(IShellState shellState, HttpState programState)\n        {\n            return $\"{Verb.ToLowerInvariant()} - Issues a {Verb.ToUpperInvariant()} request\";\n        }\n\n        protected override IEnumerable<string> GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput<ICoreParseResult> commandInput, string normalCompletionString)\n        {\n            List<string> results = new List<string>();\n\n            if (programState.Structure != null && programState.BaseAddress != null)\n            {\n                //If it's an absolute URI, nothing to suggest\n                if (Uri.TryCreate(parseResult.Sections[1], UriKind.Absolute, out Uri _))\n                {\n                    return null;\n                }\n\n                string path = normalCompletionString.Replace('\\\\', '/');\n                int searchFrom = normalCompletionString.Length - 1;\n                int lastSlash = path.LastIndexOf('/', searchFrom);\n                string prefix;\n\n                if (lastSlash < 0)\n                {\n                    path = string.Empty;\n                    prefix = normalCompletionString;\n                }\n                else\n                {\n                    path = path.Substring(0, lastSlash + 1);\n                    prefix = normalCompletionString.Substring(lastSlash + 1);\n                }\n\n                IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse()).TraverseTo(path);\n\n                foreach (string child in s.DirectoryNames)\n                {\n                    if (child.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))\n                    {\n                        results.Add(path + child);\n                    }\n                }\n            }\n\n            return results;\n        }\n\n        protected override IEnumerable<string> GetOptionValueCompletions(IShellState shellState, HttpState programState, string optionId, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, string normalizedCompletionText)\n        {\n            if (string.Equals(optionId, BodyFileOption, StringComparison.Ordinal) || string.Equals(optionId, ResponseFileOption, StringComparison.OrdinalIgnoreCase) || string.Equals(optionId, ResponseBodyFileOption, StringComparison.OrdinalIgnoreCase) || string.Equals(optionId, ResponseHeadersFileOption, StringComparison.OrdinalIgnoreCase))\n            {\n                return FileSystemCompletion.GetCompletions(normalizedCompletionText);\n            }\n\n            if (string.Equals(optionId, HeaderOption, StringComparison.Ordinal))\n            {\n                HashSet<string> alreadySpecifiedHeaders = new HashSet<string>(StringComparer.Ordinal);\n                IReadOnlyList<InputElement> options = commandInput.Options[HeaderOption];\n                for (int i = 0; i < options.Count; ++i)\n                {\n                    if (options[i] == commandInput.SelectedElement)\n                    {\n                        continue;\n                    }\n\n                    string elementText = options[i].Text;\n                    string existingHeaderName = elementText.Split(HeaderSeparatorChars)[0];\n                    alreadySpecifiedHeaders.Add(existingHeaderName);\n                }\n\n                //Check to see if the selected element is in a header name or value\n                int equalsIndex = normalizedCompletionText.IndexOfAny(HeaderSeparatorChars);\n                string path = commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty;\n\n                if (equalsIndex < 0)\n                {\n                    IEnumerable<string> headerNameOptions = HeaderCompletion.GetCompletions(alreadySpecifiedHeaders, normalizedCompletionText);\n\n                    if (headerNameOptions == null)\n                    {\n                        return null;\n                    }\n\n                    List<string> allSuggestions = new List<string>();\n                    foreach (string suggestion in headerNameOptions.Select(x => x))\n                    {\n                        allSuggestions.Add(suggestion + \":\");\n\n                        IEnumerable<string> suggestions = HeaderCompletion.GetValueCompletions(Verb, path, suggestion, string.Empty, programState);\n\n                        if (suggestions != null)\n                        {\n                            foreach (string valueSuggestion in suggestions)\n                            {\n                                allSuggestions.Add(suggestion + \":\" + valueSuggestion);\n                            }\n                        }\n                    }\n\n                    return allSuggestions;\n                }\n                else\n                {\n                    //Didn't exit from the header name check, so must be a value\n                    string headerName = normalizedCompletionText.Substring(0, equalsIndex);\n                    IEnumerable<string> suggestions = HeaderCompletion.GetValueCompletions(Verb, path, headerName, normalizedCompletionText.Substring(equalsIndex + 1), programState);\n\n                    if (suggestions == null)\n                    {\n                        return null;\n                    }\n\n                    return suggestions.Select(x => normalizedCompletionText.Substring(0, equalsIndex + 1) + x);\n                }\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.HttpRepl.Suggestions;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class ChangeDirectoryCommand : CommandWithStructuredInputBase<HttpState, ICoreParseResult>\n    {\n        protected override Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)\n        {\n            if (commandInput.Arguments.Count == 0 || string.IsNullOrEmpty(commandInput.Arguments[0]?.Text))\n            {\n                shellState.ConsoleManager.WriteLine($\"/{string.Join(\"/\", programState.PathSections.Reverse())}\");\n            }\n            else\n            {\n                string[] parts = commandInput.Arguments[0].Text.Replace('\\\\', '/').Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);\n\n                if (commandInput.Arguments[0].Text.StartsWith(\"/\", StringComparison.Ordinal))\n                {\n                    programState.PathSections.Clear();\n                }\n\n                foreach (string part in parts)\n                {\n                    switch (part)\n                    {\n                        case \".\":\n                            break;\n                        case \"..\":\n                            if (programState.PathSections.Count > 0)\n                            {\n                                programState.PathSections.Pop();\n                            }\n                            break;\n                        default:\n                            programState.PathSections.Push(part);\n                            break;\n                    }\n                }\n\n                IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse());\n\n                string thisDirMethod = s.RequestInfo != null && s.RequestInfo.Methods.Count > 0\n                    ? \"[\" + string.Join(\"|\", s.RequestInfo.Methods) + \"]\"\n                    : \"[]\";\n\n                shellState.ConsoleManager.WriteLine($\"/{string.Join(\"/\", programState.PathSections.Reverse())}    {thisDirMethod}\");\n            }\n\n            return Task.CompletedTask;\n        }\n\n        public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create(\"cd\")\n            .MaximumArgCount(1)\n            .Finish();\n\n        protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)\n        {\n            var help = new StringBuilder();\n            help.Append(\"Usage:\".Bold());\n            help.AppendLine(\"cd [directory]\");\n            help.AppendLine();\n            help.AppendLine(\"Prints the current directory if no argument is specified, otherwise changes to the specified directory\");\n\n            return help.ToString();\n        }\n\n        public override string GetHelpSummary(IShellState shellState, HttpState programState)\n        {\n            return \"cd [directory name] - Prints the current directory if no argument is specified, otherwise changes to the specified directory\";\n        }\n\n        protected override IEnumerable<string> GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput<ICoreParseResult> commandInput, string normalCompletionString)\n        {\n            return ServerPathCompletion.GetCompletions(programState, normalCompletionString);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/ClearCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class ClearCommand : ICommand<object, ICoreParseResult>\n    {\n        private static readonly string Name = \"clear\";\n        private static readonly string AlternateName = \"cls\";\n\n        public bool? CanHandle(IShellState shellState, object programState, ICoreParseResult parseResult)\n        {\n            return parseResult.Sections.Count == 1 && (string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) || string.Equals(parseResult.Sections[0], AlternateName, StringComparison.OrdinalIgnoreCase))\n                ? (bool?) true\n                : null;\n        }\n\n        public Task ExecuteAsync(IShellState shellState, object programState, ICoreParseResult parseResult, CancellationToken cancellationToken)\n        {\n            shellState.ConsoleManager.Clear();\n            shellState.CommandDispatcher.OnReady(shellState);\n            return Task.CompletedTask;\n        }\n\n        public string GetHelpDetails(IShellState shellState, object programState, ICoreParseResult parseResult)\n        {\n            if (parseResult.Sections.Count == 1 && (string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) || string.Equals(parseResult.Sections[0], AlternateName, StringComparison.OrdinalIgnoreCase)))\n            {\n                return \"Clears the shell\";\n            }\n\n            return null;\n        }\n\n        public string GetHelpSummary(IShellState shellState, object programState)\n        {\n            return \"clear - Clears the shell\";\n        }\n\n        public IEnumerable<string> Suggest(IShellState shellState, object programState, ICoreParseResult parseResult)\n        {\n            if (parseResult.SelectedSection == 0 && \n                (string.IsNullOrEmpty(parseResult.Sections[parseResult.SelectedSection]) || Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))\n            {\n                return new[] { Name };\n            }\n\n            if (parseResult.SelectedSection == 0 &&\n                (string.IsNullOrEmpty(parseResult.Sections[parseResult.SelectedSection]) || AlternateName.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))\n            {\n                return new[] { Name };\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/ConfigCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Net.Http;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.HttpRepl.Diagnostics;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class ConfigCommand : CommandWithStructuredInputBase<HttpState, ICoreParseResult>\n    {\n        protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)\n        {\n            if (programState.BaseAddress == null)\n            {\n                shellState.ConsoleManager.Error.WriteLine(\"Must be connected to a server to query configuration\".SetColor(programState.ErrorColor));\n                return;\n            }\n\n            if (string.IsNullOrEmpty(programState.DiagnosticsState.DiagnosticsEndpoint))\n            {\n                shellState.ConsoleManager.Error.WriteLine(\"Diagnostics endpoint must be set to query configuration (see set diag)\".SetColor(programState.ErrorColor));\n                return;\n            }\n\n            string configUrl = programState.DiagnosticsState.DiagnosticItems.FirstOrDefault(x => x.DisplayName == \"Configuration\")?.Url;\n\n            if (configUrl == null)\n            {\n                shellState.ConsoleManager.Error.WriteLine(\"Diagnostics endpoint does not expose configuration information\".SetColor(programState.ErrorColor));\n                return;\n            }\n\n            HttpResponseMessage response = await programState.Client.GetAsync(new Uri(programState.BaseAddress, configUrl), cancellationToken).ConfigureAwait(false);\n\n            if (!response.IsSuccessStatusCode)\n            {\n                shellState.ConsoleManager.Error.WriteLine(\"Unable to get configuration information from diagnostics endpoint\".SetColor(programState.ErrorColor));\n                return;\n            }\n\n            List<ConfigItem> configItems = await response.Content.ReadAsAsync<List<ConfigItem>>(cancellationToken).ConfigureAwait(false);\n\n            foreach (ConfigItem item in configItems)\n            {\n                shellState.ConsoleManager.WriteLine($\"{item.Key.Cyan()}: {item.Value}\");\n            }\n        }\n\n        public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create(\"config\").Finish();\n\n        protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)\n        {\n            return \"config - Gets configuration information for the site if connected to a diagnostics endpoint\";\n        }\n\n        public override string GetHelpSummary(IShellState shellState, HttpState programState)\n        {\n            return \"config - Gets configuration information for the site if connected to a diagnostics endpoint\";\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/DeleteCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class DeleteCommand : BaseHttpCommand\n    {\n        protected override string Verb => \"delete\";\n\n        protected override bool RequiresBody => false;\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/EchoCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class EchoCommand : CommandWithStructuredInputBase<HttpState, ICoreParseResult>\n    {\n        private readonly HashSet<string> _allowedModes = new HashSet<string>(StringComparer.OrdinalIgnoreCase) {\"on\", \"off\"};\n\n        protected override bool CanHandle(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput)\n        {\n            if (commandInput.Arguments.Count == 0 || !_allowedModes.Contains(commandInput.Arguments[0]?.Text))\n            {\n                shellState.ConsoleManager.Error.WriteLine(\"Allowed echo modes are 'on' and 'off'\".SetColor(programState.ErrorColor));\n                return false;\n            }\n\n            return true;\n        }\n\n        protected override Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)\n        {\n            bool turnOn = string.Equals(commandInput.Arguments[0].Text, \"on\", StringComparison.OrdinalIgnoreCase);\n            programState.EchoRequest = turnOn;\n\n            shellState.ConsoleManager.WriteLine(\"Request echoing is \" + (turnOn ? \"on\" : \"off\"));\n            return Task.CompletedTask;\n        }\n\n        public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create(\"echo\").ExactArgCount(1).Finish();\n\n        protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)\n        {\n            var helpText = new StringBuilder();\n            helpText.Append(\"Usage: \".Bold());\n            helpText.AppendLine($\"echo [on|off]\");\n            helpText.AppendLine();\n            helpText.AppendLine($\"Turns request echoing on or off. When request echoing is on we will display a text representation of requests made by the CLI.\");\n            return helpText.ToString();\n        }\n\n        public override string GetHelpSummary(IShellState shellState, HttpState programState)\n        {\n            return \"echo [on/off] - Turns request echoing on or off\";\n        }\n\n        protected override IEnumerable<string> GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput<ICoreParseResult> commandInput, string normalCompletionString)\n        {\n            List<string> result = _allowedModes.Where(x => x.StartsWith(normalCompletionString, StringComparison.OrdinalIgnoreCase)).ToList();\n            return result.Count > 0 ? result : null;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/ExitCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Text;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class ExitCommand : CommandWithStructuredInputBase<object, ICoreParseResult>\n    {\n        protected override Task ExecuteAsync(IShellState shellState, object programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)\n        {\n            shellState.IsExiting = true;\n            return Task.CompletedTask;\n        }\n\n        public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create(\"exit\").ExactArgCount(0).Finish();\n\n        protected override string GetHelpDetails(IShellState shellState, object programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)\n        {\n            var helpText = new StringBuilder();\n            helpText.Append(\"Usage: \".Bold());\n            helpText.AppendLine($\"exit\");\n            helpText.AppendLine();\n            helpText.AppendLine($\"Exits the shell\");\n            return helpText.ToString();\n        }\n\n        public override string GetHelpSummary(IShellState shellState, object programState)\n        {\n            return \"exit - Exits the shell\";\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/Formatter.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class Formatter\n    {\n        private int _prefix;\n        private int _maxDepth;\n\n        public void RegisterEntry(int prefixLength, int depth)\n        {\n            if (depth > _maxDepth)\n            {\n                _maxDepth = depth;\n            }\n\n            if (prefixLength > _prefix)\n            {\n                _prefix = prefixLength;\n            }\n        }\n\n        public string Format(string prefix, string entry, int level)\n        {\n            string indent = \"\".PadRight(level * 4);\n            return (indent + prefix).PadRight(_prefix + 3 + _maxDepth * 4) + entry;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/GetCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class GetCommand : BaseHttpCommand\n    {\n        protected override string Verb => \"get\";\n\n        protected override bool RequiresBody => false;\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/HeadCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class HeadCommand : BaseHttpCommand\n    {\n        protected override string Verb => \"head\";\n\n        protected override bool RequiresBody => false;\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/HelpCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.HttpRepl.Preferences;\nusing Microsoft.HttpRepl.Suggestions;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class HelpCommand : ICommand<HttpState, ICoreParseResult>\n    {\n        private static readonly string Name = \"help\";\n\n        public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            return parseResult.Sections.Count > 0 && string.Equals(parseResult.Sections[0], Name)\n                ? (bool?)true\n                : null;\n        }\n\n        public async Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken)\n        {\n            if (shellState.CommandDispatcher is ICommandDispatcher<HttpState, ICoreParseResult> dispatcher)\n            {\n                if (parseResult.Sections.Count == 1)\n                {\n                    CoreGetHelp(shellState, dispatcher, programState);\n                }\n                else\n                {\n                    bool anyHelp = false;\n\n                    if (parseResult.Slice(1) is ICoreParseResult continuationParseResult)\n                    {\n                        foreach (ICommand<HttpState, ICoreParseResult> command in dispatcher.Commands)\n                        {\n                            string help = command.GetHelpDetails(shellState, programState, continuationParseResult);\n\n                            if (!string.IsNullOrEmpty(help))\n                            {\n                                anyHelp = true;\n                                shellState.ConsoleManager.WriteLine();\n                                shellState.ConsoleManager.WriteLine(help);\n\n                                var structuredCommand = command as CommandWithStructuredInputBase<HttpState, ICoreParseResult>;\n                                if (structuredCommand != null && structuredCommand.InputSpec.Options.Any())\n                                {\n                                    shellState.ConsoleManager.WriteLine();\n                                    shellState.ConsoleManager.WriteLine(\"Options:\".Bold());\n                                    foreach (var option in structuredCommand.InputSpec.Options)\n                                    {\n                                        var optionText = string.Empty;\n                                        foreach (var form in option.Forms)\n                                        {\n                                            if (!string.IsNullOrEmpty(optionText))\n                                            {\n                                                optionText += \"|\";\n                                            }\n                                            optionText += form;\n                                        }\n                                        shellState.ConsoleManager.WriteLine($\"    {optionText}\");\n                                    }\n                                }\n\n                                break;\n                            }\n                        }\n                    }\n\n                    if (!anyHelp)\n                    {\n                        //Maybe the input is an URL\n                        if (parseResult.Sections.Count == 2)\n                        {\n\n                            if (programState.SwaggerEndpoint != null)\n                            {\n                                string swaggerRequeryBehaviorSetting = programState.GetStringPreference(WellKnownPreference.SwaggerRequeryBehavior, \"auto\");\n\n                                if (swaggerRequeryBehaviorSetting.StartsWith(\"auto\", StringComparison.OrdinalIgnoreCase))\n                                {\n                                    await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, programState, programState.SwaggerEndpoint, cancellationToken).ConfigureAwait(false);\n                                }\n                            }\n\n                            //Structure is null because, for example, SwaggerEndpoint exists but is not reachable.\n                            if (programState.Structure != null)\n                            {\n                                IDirectoryStructure structure = programState.Structure.TraverseTo(parseResult.Sections[1]);\n                                if (structure.DirectoryNames.Any())\n                                {\n                                    shellState.ConsoleManager.WriteLine(\"Child directories:\");\n\n                                    foreach (string name in structure.DirectoryNames)\n                                    {\n                                        shellState.ConsoleManager.WriteLine(\"  \" + name + \"/\");\n                                    }\n                                    anyHelp = true;\n                                }\n\n                                if (structure.RequestInfo != null)\n                                {\n                                    if (structure.RequestInfo.Methods.Count > 0)\n                                    {\n                                        if (anyHelp)\n                                        {\n                                            shellState.ConsoleManager.WriteLine();\n                                        }\n\n                                        anyHelp = true;\n                                        shellState.ConsoleManager.WriteLine(\"Available methods:\");\n\n                                        foreach (string method in structure.RequestInfo.Methods)\n                                        {\n                                            shellState.ConsoleManager.WriteLine(\"  \" + method.ToUpperInvariant());\n                                            IReadOnlyList<string> accepts = structure.RequestInfo.ContentTypesByMethod[method];\n                                            string acceptsString = string.Join(\", \", accepts.Where(x => !string.IsNullOrEmpty(x)));\n                                            if (!string.IsNullOrEmpty(acceptsString))\n                                            {\n                                                shellState.ConsoleManager.WriteLine(\"    Accepts: \" + acceptsString);\n                                            }\n                                        }\n                                    }\n                                }\n                            }\n                        }\n\n                        if (!anyHelp)\n                        {\n                            shellState.ConsoleManager.WriteLine(\"Unable to locate any help information for the specified command\");\n                        }\n                    }\n                }\n            }\n        }\n\n        public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            if (parseResult.Sections.Count > 0 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase))\n            {\n                if (parseResult.Sections.Count > 1)\n                {\n                    return \"Gets help about \" + parseResult.Slice(1).CommandText;\n                }\n                else\n                {\n                    return \"Gets help\";\n                }\n            }\n\n            return null;\n        }\n\n        public string GetHelpSummary(IShellState shellState, HttpState programState)\n        {\n            return \"help - Gets help\";\n        }\n\n        public IEnumerable<string> Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            if (parseResult.SelectedSection == 0 &&\n                (string.IsNullOrEmpty(parseResult.Sections[parseResult.SelectedSection]) || Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))\n            {\n                return new[] { Name };\n            }\n            else if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase))\n            {\n                if (shellState.CommandDispatcher is ICommandDispatcher<HttpState, ICoreParseResult> dispatcher \n                    && parseResult.Slice(1) is ICoreParseResult continuationParseResult)\n                {\n                    HashSet<string> suggestions = new HashSet<string>(StringComparer.OrdinalIgnoreCase);\n\n                    foreach (ICommand<HttpState, ICoreParseResult> command in dispatcher.Commands)\n                    {\n                        IEnumerable<string> commandSuggestions = command.Suggest(shellState, programState, continuationParseResult);\n\n                        if (commandSuggestions != null)\n                        {\n                            suggestions.UnionWith(commandSuggestions);\n                        }\n                    }\n\n                    if (continuationParseResult.SelectedSection == 0)\n                    {\n                        string normalizedCompletionText = continuationParseResult.Sections[0].Substring(0, continuationParseResult.CaretPositionWithinSelectedSection);\n                        suggestions.UnionWith(ServerPathCompletion.GetCompletions(programState, normalizedCompletionText));\n                    }\n\n                    return suggestions.OrderBy(x => x, StringComparer.OrdinalIgnoreCase).ToList();\n                }\n            }\n\n            return null;\n        }\n\n        public void CoreGetHelp(IShellState shellState, ICommandDispatcher<HttpState, ICoreParseResult> dispatcher, HttpState programState)\n        {\n            shellState.ConsoleManager.WriteLine();\n            shellState.ConsoleManager.WriteLine(\"HTTP Commands:\".Bold().Cyan());\n            shellState.ConsoleManager.WriteLine(\"Use these commands to execute requests against your application.\");\n            shellState.ConsoleManager.WriteLine();\n\n            const int navCommandColumn = -15;\n\n            shellState.ConsoleManager.WriteLine($\"{\"GET\",navCommandColumn}{\"Issues a GET request.\"}\");\n            shellState.ConsoleManager.WriteLine($\"{\"POST\",navCommandColumn}{\"Issues a POST request.\"}\");\n            shellState.ConsoleManager.WriteLine($\"{\"PUT\",navCommandColumn}{\"Issues a PUT request.\"}\");\n            shellState.ConsoleManager.WriteLine($\"{\"DELETE\",navCommandColumn}{\"Issues a DELETE request.\"}\");\n            shellState.ConsoleManager.WriteLine($\"{\"PATCH\",navCommandColumn}{\"Issues a PATCH request.\"}\");\n            shellState.ConsoleManager.WriteLine($\"{\"HEAD\",navCommandColumn}{\"Issues a HEAD request.\"}\");\n            shellState.ConsoleManager.WriteLine($\"{\"OPTIONS\",navCommandColumn}{\"Issues an OPTIONS request.\"}\");\n            shellState.ConsoleManager.WriteLine();\n            shellState.ConsoleManager.WriteLine($\"{\"set header\",navCommandColumn}{\"Sets or clears a header for all requests. e.g. `set header content-type application/json`\"}\");\n            shellState.ConsoleManager.WriteLine();\n\n            shellState.ConsoleManager.WriteLine();\n            shellState.ConsoleManager.WriteLine(\"Navigation Commands:\".Bold().Cyan());\n            shellState.ConsoleManager.WriteLine(\"The REPL allows you to navigate your URL space and focus on specific APIS that you are working on.\");\n            shellState.ConsoleManager.WriteLine();\n\n            shellState.ConsoleManager.WriteLine($\"{\"set base\",navCommandColumn}{\"Set the base URI. e.g. `set base http://locahost:5000`\"}\");\n            shellState.ConsoleManager.WriteLine($\"{\"set swagger\",navCommandColumn}{\"Set the URI, relative to your base if set, of the Swagger document for this API. e.g. `set swagger /swagger/v1/swagger.json`\"}\");\n            shellState.ConsoleManager.WriteLine($\"{\"ls\",navCommandColumn}{\"Show all endpoints for the current path.\"}\");\n            shellState.ConsoleManager.WriteLine($\"{\"cd\",navCommandColumn}{\"Append the given directory to the currently selected path, or move up a path when using `cd ..`.\"}\");\n\n            shellState.ConsoleManager.WriteLine();\n            shellState.ConsoleManager.WriteLine(\"Shell Commands:\".Bold().Cyan());\n            shellState.ConsoleManager.WriteLine(\"Use these commands to interact with the REPL shell.\");\n            shellState.ConsoleManager.WriteLine();\n\n            shellState.ConsoleManager.WriteLine($\"{\"clear\",navCommandColumn}{\"Removes all text from the shell.\"}\");\n            shellState.ConsoleManager.WriteLine($\"{\"echo [on/off]\",navCommandColumn}{\"Turns request echoing on or off, show the request that was mode when using request commands.\"}\");\n            shellState.ConsoleManager.WriteLine($\"{\"exit\",navCommandColumn}{\"Exit the shell.\"}\");\n\n            shellState.ConsoleManager.WriteLine();\n            shellState.ConsoleManager.WriteLine(\"REPL Customization Commands:\".Bold().Cyan());\n            shellState.ConsoleManager.WriteLine(\"Use these commands to customize the REPL behavior..\");\n            shellState.ConsoleManager.WriteLine();\n\n            shellState.ConsoleManager.WriteLine($\"{\"pref [get/set]\",navCommandColumn}{\"Allows viewing or changing preferences, e.g. 'pref set editor.command.default 'C:\\\\Program Files\\\\Microsoft VS Code\\\\Code.exe'`\"}\");\n            shellState.ConsoleManager.WriteLine($\"{\"run\",navCommandColumn}{\"Runs the script at the given path. A script is a set of commands that can be typed with one command per line.\"}\");\n            shellState.ConsoleManager.WriteLine($\"{\"ui\",navCommandColumn}{\"Displays the swagger UI page, if available, in the default browser.\"}\");\n            shellState.ConsoleManager.WriteLine();\n            shellState.ConsoleManager.WriteLine(\"Use help <COMMAND> to learn more details about individual commands. e.g. `help get`\".Bold().Cyan());\n            shellState.ConsoleManager.WriteLine();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/ListCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Text;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.HttpRepl.Preferences;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class ListCommand : CommandWithStructuredInputBase<HttpState, ICoreParseResult>\n    {\n        private const string RecursiveOption = nameof(RecursiveOption);\n\n        protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)\n        {\n            if (programState.SwaggerEndpoint != null)\n            {\n                string swaggerRequeryBehaviorSetting = programState.GetStringPreference(WellKnownPreference.SwaggerRequeryBehavior, \"auto\");\n\n                if (swaggerRequeryBehaviorSetting.StartsWith(\"auto\", StringComparison.OrdinalIgnoreCase))\n                {\n                    await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, programState, programState.SwaggerEndpoint, cancellationToken).ConfigureAwait(false);\n                }\n            }\n\n            if (programState.Structure == null || programState.BaseAddress == null)\n            {\n                return;\n            }\n\n            string path = commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty;\n\n            //If it's an absolute URI, nothing to suggest\n            if (Uri.TryCreate(path, UriKind.Absolute, out Uri _))\n            {\n                return;\n            }\n\n            IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse()).TraverseTo(path);\n\n            string thisDirMethod = s.RequestInfo != null && s.RequestInfo.Methods.Count > 0\n                ? \"[\" + string.Join(\"|\", s.RequestInfo.Methods) + \"]\"\n                : \"[]\";\n\n            List<TreeNode> roots = new List<TreeNode>();\n            Formatter formatter = new Formatter();\n\n            roots.Add(new TreeNode(formatter, \".\", thisDirMethod));\n\n            if (s.Parent != null)\n            {\n                string parentDirMethod = s.Parent.RequestInfo != null && s.Parent.RequestInfo.Methods.Count > 0\n                    ? \"[\" + string.Join(\"|\", s.Parent.RequestInfo.Methods) + \"]\"\n                    : \"[]\";\n\n                roots.Add(new TreeNode(formatter, \"..\", parentDirMethod));\n            }\n\n            int recursionDepth = 1;\n\n            if (commandInput.Options[RecursiveOption].Count > 0)\n            {\n                if (string.IsNullOrEmpty(commandInput.Options[RecursiveOption][0]?.Text))\n                {\n                    recursionDepth = int.MaxValue;\n                }\n                else if (int.TryParse(commandInput.Options[RecursiveOption][0].Text, NumberStyles.Integer, CultureInfo.InvariantCulture, out int rd) && rd > 1)\n                {\n                    recursionDepth = rd;\n                }\n            }\n\n            foreach (string child in s.DirectoryNames)\n            {\n                IDirectoryStructure dir = s.GetChildDirectory(child);\n\n                string methods = dir.RequestInfo != null && dir.RequestInfo.Methods.Count > 0 \n                    ? \"[\" + string.Join(\"|\", dir.RequestInfo.Methods) + \"]\" \n                    : \"[]\";\n\n                TreeNode dirNode = new TreeNode(formatter, child, methods);\n                roots.Add(dirNode);\n                Recurse(dirNode, dir, recursionDepth - 1);\n            }\n\n            foreach (TreeNode node in roots)\n            {\n                shellState.ConsoleManager.WriteLine(node.ToString());\n            }\n        }\n\n        private static void Recurse(TreeNode parentNode, IDirectoryStructure parent, int remainingDepth)\n        {\n            if (remainingDepth <= 0)\n            {\n                return;\n            }\n\n            foreach (string child in parent.DirectoryNames)\n            {\n                IDirectoryStructure dir = parent.GetChildDirectory(child);\n\n                string methods = dir.RequestInfo != null && dir.RequestInfo.Methods.Count > 0 \n                    ? \"[\" + string.Join(\"|\", dir.RequestInfo.Methods) + \"]\" \n                    : \"[]\";\n\n                TreeNode node = parentNode.AddChild(child, methods);\n                Recurse(node, dir, remainingDepth - 1);\n            }\n        }\n\n\n\n        public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create(\"ls\").AlternateName(\"dir\")\n            .MaximumArgCount(1)\n            .WithOption(new CommandOptionSpecification(RecursiveOption, maximumOccurrences: 1, acceptsValue: true, forms: new[] {\"-r\", \"--recursive\"}))\n            .Finish();\n\n        protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)\n        {\n            var helpText = new StringBuilder();\n            helpText.Append(\"Usage: \".Bold());\n            helpText.AppendLine($\"ls [Options]\");\n            helpText.AppendLine();\n            helpText.AppendLine($\"Displays the known routes at the current location. Requires a Swagger document to be set.\");\n            return helpText.ToString();\n        }\n\n        public override string GetHelpSummary(IShellState shellState, HttpState programState)\n        {\n            return \"ls - List known routes for the current location\";\n        }\n\n        protected override IEnumerable<string> GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput<ICoreParseResult> commandInput, string normalCompletionString)\n        {\n            if (programState.Structure == null || programState.BaseAddress == null)\n            {\n                return null;\n            }\n\n            //If it's an absolute URI, nothing to suggest\n            if (Uri.TryCreate(normalCompletionString, UriKind.Absolute, out Uri _))\n            {\n                return null;\n            }\n\n            string path = normalCompletionString.Replace('\\\\', '/');\n            int searchFrom = normalCompletionString.Length - 1;\n            int lastSlash = path.LastIndexOf('/', searchFrom);\n            string prefix;\n\n            if (lastSlash < 0)\n            {\n                path = string.Empty;\n                prefix = normalCompletionString;\n            }\n            else\n            {\n                path = path.Substring(0, lastSlash + 1);\n                prefix = normalCompletionString.Substring(lastSlash + 1);\n            }\n\n            IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse()).TraverseTo(path);\n\n            List<string> results = new List<string>();\n\n            foreach (string child in s.DirectoryNames)\n            {\n                if (child.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))\n                {\n                    results.Add(path + child);\n                }\n            }\n\n            return results;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/OptionsCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class OptionsCommand : BaseHttpCommand\n    {\n        protected override string Verb => \"options\";\n\n        protected override bool RequiresBody => false;\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/PatchCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class PatchCommand : BaseHttpCommand\n    {\n        protected override string Verb => \"patch\";\n\n        protected override bool RequiresBody => true;\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/PostCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class PostCommand : BaseHttpCommand\n    {\n        protected override string Verb => \"post\";\n\n        protected override bool RequiresBody => true;\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/PrefCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.HttpRepl.Preferences;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class PrefCommand : CommandWithStructuredInputBase<HttpState, ICoreParseResult>\n    {\n        private readonly HashSet<string> _allowedSubcommands = new HashSet<string>(StringComparer.OrdinalIgnoreCase) {\"get\", \"set\"};\n\n        public override string GetHelpSummary(IShellState shellState, HttpState programState)\n        {\n            return \"pref [get/set] {setting} [{value}] - Allows viewing or changing preferences\";\n        }\n\n        protected override bool CanHandle(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput)\n        {\n            if (commandInput.Arguments.Count == 0 || !_allowedSubcommands.Contains(commandInput.Arguments[0]?.Text))\n            {\n                shellState.ConsoleManager.Error.WriteLine(\"Whether get or set settings must be specified\");\n                return false;\n            }\n\n            if (!string.Equals(\"get\", commandInput.Arguments[0].Text) && (commandInput.Arguments.Count < 2 || string.IsNullOrEmpty(commandInput.Arguments[1]?.Text)))\n            {\n                shellState.ConsoleManager.Error.WriteLine(\"The preference to set must be specified\");\n                return false;\n            }\n\n            return true;\n        }\n\n        protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)\n        {\n            var helpText = new StringBuilder();\n            helpText.Append(\"Usage: \".Bold());\n\n            if (commandInput.Arguments.Count == 0 || !_allowedSubcommands.Contains(commandInput.Arguments[0]?.Text))\n            {\n                helpText.AppendLine(\"pref [get/set] {setting} [{value}] - Get or sets a preference to a particular value\");\n            }\n            else if (string.Equals(commandInput.Arguments[0].Text, \"get\", StringComparison.OrdinalIgnoreCase))\n            {\n                helpText.AppendLine(\"pref get [{setting}] - Gets the value of the specified preference or lists all preferences if no preference is specified\");\n            }\n            else\n            {\n                helpText.AppendLine(\"pref set {setting} [{value}] - Sets (or clears if value is not specified) the value of the specified preference\");\n            }\n\n            helpText.AppendLine();\n            helpText.AppendLine(\"Current Default Preferences:\");\n            foreach (var pref in programState.DefaultPreferences)\n            {\n                var val = pref.Value;\n                if (pref.Key.Contains(\"colors\"))\n                {\n                    val = GetColor(val);\n                }\n                helpText.AppendLine($\"{pref.Key,-50}{val}\");\n            }\n            helpText.AppendLine();\n            helpText.AppendLine(\"Current Preferences:\");\n            foreach (var pref in programState.Preferences)\n            {\n                var val = pref.Value;\n                if (pref.Key.Contains(\"colors\"))\n                {\n                    val = GetColor(val);\n                }\n                helpText.AppendLine($\"{pref.Key,-50}{val}\");\n            }\n\n            return helpText.ToString();\n        }\n\n        private static string GetColor(string value)\n        {\n            if (value.Contains(\"Bold\"))\n            {\n                value = value.Bold();\n            }\n\n            if (value.Contains(\"Yellow\"))\n            {\n                value = value.Yellow();\n            }\n\n            if (value.Contains(\"Cyan\"))\n            {\n                value = value.Cyan();\n            }\n\n            if (value.Contains(\"Magenta\"))\n            {\n                value = value.Magenta();\n            }\n\n            if (value.Contains(\"Green\"))\n            {\n                value = value.Green();\n            }\n\n            if (value.Contains(\"White\"))\n            {\n                value = value.White();\n            }\n\n            if (value.Contains(\"Black\"))\n            {\n                value = value.Black();\n            }\n\n            return value;\n        }\n\n        protected override Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)\n        {\n            if (string.Equals(commandInput.Arguments[0].Text, \"get\", StringComparison.OrdinalIgnoreCase))\n            {\n                return GetSetting(shellState, programState, commandInput);\n            }\n\n            return SetSetting(shellState, programState, commandInput);\n        }\n\n        private static Task SetSetting(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput)\n        {\n            string prefName = commandInput.Arguments[1].Text;\n            string prefValue = commandInput.Arguments.Count > 2 ? commandInput.Arguments[2]?.Text : null;\n\n            if (string.IsNullOrEmpty(prefValue))\n            {\n                if (!programState.DefaultPreferences.TryGetValue(prefName, out string defaultValue))\n                {\n                    programState.Preferences.Remove(prefName);\n                }\n                else\n                {\n                    programState.Preferences[prefName] = defaultValue;\n                }\n            }\n            else\n            {\n                programState.Preferences[prefName] = prefValue;\n            }\n\n            if (!programState.SavePreferences())\n            {\n                shellState.ConsoleManager.Error.WriteLine(\"Error saving preferences\".SetColor(programState.ErrorColor));\n            }\n\n            return Task.CompletedTask;\n        }\n\n        private static Task GetSetting(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput)\n        {\n            string preferenceName = commandInput.Arguments.Count > 1 ? commandInput.Arguments[1]?.Text : null;\n            \n            //If there's a particular setting to get the value of\n            if (!string.IsNullOrEmpty(preferenceName))\n            {\n                if (programState.Preferences.TryGetValue(preferenceName, out string value))\n                {\n                    shellState.ConsoleManager.WriteLine(\"Configured value: \" + value);\n                }\n                else\n                {\n                    shellState.ConsoleManager.Error.WriteLine((commandInput.Arguments[1].Text + \" does not have a configured value\").SetColor(programState.ErrorColor));\n                }\n            }\n            else\n            {\n                foreach (KeyValuePair<string, string> entry in programState.Preferences.OrderBy(x => x.Key))\n                {\n                    shellState.ConsoleManager.WriteLine($\"{entry.Key}={entry.Value}\");\n                }\n            }\n\n            return Task.CompletedTask;\n        }\n\n        public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create(\"pref\")\n            .MinimumArgCount(1)\n            .MaximumArgCount(3)\n            .Finish();\n\n\n        protected override IEnumerable<string> GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput<ICoreParseResult> commandInput, string normalCompletionString)\n        {\n            if (parseResult.SelectedSection == 1)\n            {\n                return _allowedSubcommands.Where(x => x.StartsWith(normalCompletionString, StringComparison.OrdinalIgnoreCase));\n            }\n\n            if (parseResult.SelectedSection == 2)\n            {\n                string prefix = parseResult.Sections.Count > 2 ? normalCompletionString : string.Empty;\n                List<string> matchingProperties = new List<string>();\n\n                foreach (string val in WellKnownPreference.Catalog.Names)\n                {\n                    if (val.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))\n                    {\n                        matchingProperties.Add(val);\n                    }\n                }\n\n                return matchingProperties;\n            }\n\n            if (parseResult.SelectedSection == 3\n                && parseResult.Sections[2].StartsWith(\"colors.\", StringComparison.OrdinalIgnoreCase))\n            {\n                string prefix = parseResult.Sections.Count > 3 ? normalCompletionString : string.Empty;\n                List<string> matchingProperties = new List<string>();\n\n                foreach (string val in Enum.GetNames(typeof(AllowedColors)))\n                {\n                    if (val.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))\n                    {\n                        matchingProperties.Add(val);\n                    }\n                }\n\n                return matchingProperties;\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/PutCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class PutCommand : BaseHttpCommand\n    {\n        protected override string Verb => \"put\";\n\n        protected override bool RequiresBody => true;\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/RunCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Text;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\nusing Microsoft.Repl.Scripting;\nusing Microsoft.Repl.Suggestions;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class RunCommand : ICommand<HttpState, ICoreParseResult>\n    {\n        private static readonly string Name = \"run\";\n\n        public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            return parseResult.Sections.Count > 1 && parseResult.Sections.Count < 4 && string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase)\n                ? (bool?)true\n                : null;\n        }\n\n        public async Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken)\n        {\n            if (!File.Exists(parseResult.Sections[1]))\n            {\n                shellState.ConsoleManager.Error.WriteLine($\"Could not file script file {parseResult.Sections[1]}\");\n                return;\n            }\n\n            bool suppressScriptLinesInHistory = true;\n            if (parseResult.Sections.Count == 3)\n            {\n                suppressScriptLinesInHistory = !string.Equals(parseResult.Sections[2], \"+history\");\n            }\n\n            string[] lines = File.ReadAllLines(parseResult.Sections[1]);\n            IScriptExecutor scriptExecutor = new ScriptExecutor<HttpState, ICoreParseResult>(suppressScriptLinesInHistory);\n            await scriptExecutor.ExecuteScriptAsync(shellState, lines, cancellationToken).ConfigureAwait(false);\n        }\n\n        public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            if (parseResult.Sections.Count > 0 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase))\n            {\n                var helpText = new StringBuilder();\n                helpText.Append(\"Usage: \".Bold());\n                helpText.AppendLine(\"run {path to script}\");\n                helpText.AppendLine();\n                helpText.AppendLine(\"Runs the specified script.\");\n                helpText.AppendLine(\"A script is a text file containing one CLI command per line. Each line will be run as if it was typed into the CLI.\");\n                return helpText.ToString();\n            }\n\n            return null;\n        }\n\n        public string GetHelpSummary(IShellState shellState, HttpState programState)\n        {\n            return \"run {path to script} - Runs a script\";\n        }\n\n        public IEnumerable<string> Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            if (parseResult.SelectedSection == 0 &&\n                (string.IsNullOrEmpty(parseResult.Sections[parseResult.SelectedSection]) || Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))\n            {\n                return new[] { Name };\n            }\n\n            if (parseResult.SelectedSection == 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase))\n            {\n                return FileSystemCompletion.GetCompletions(parseResult.Sections[1].Substring(0, parseResult.CaretPositionWithinSelectedSection));\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Net.Http;\nusing System.Net.Sockets;\nusing System.Text;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class SetBaseCommand : ICommand<HttpState, ICoreParseResult>\n    {\n        private const string Name = \"set\";\n        private const string SubCommand = \"base\";\n\n        public string Description => \"Sets the base address to direct requests to.\";\n\n        public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            return parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase)\n                ? (bool?)true\n                : null;\n        }\n\n        public async Task ExecuteAsync(IShellState shellState, HttpState state, ICoreParseResult parseResult, CancellationToken cancellationToken)\n        {\n            if (parseResult.Sections.Count == 2)\n            {\n                state.BaseAddress = null;\n            }\n            else if (parseResult.Sections.Count != 3 || string.IsNullOrEmpty(parseResult.Sections[2]) || !Uri.TryCreate(EnsureTrailingSlash(parseResult.Sections[2]), UriKind.Absolute, out Uri serverUri))\n            {\n                shellState.ConsoleManager.Error.WriteLine(\"Must specify a server\".SetColor(state.ErrorColor));\n            }\n            else\n            {\n                state.BaseAddress = serverUri;\n                try\n                {\n                    await state.Client.SendAsync(new HttpRequestMessage(HttpMethod.Head, serverUri)).ConfigureAwait(false);\n                }\n                catch (Exception ex) when (ex.InnerException is SocketException se)\n                {\n                    shellState.ConsoleManager.Error.WriteLine($\"Warning: HEAD request to the specified address was unsuccessful ({se.Message})\".SetColor(state.WarningColor));\n                }\n                catch { }\n            }\n\n            if (state.BaseAddress == null || !Uri.TryCreate(state.BaseAddress, \"swagger.json\", out Uri result))\n            {\n                state.SwaggerStructure = null;\n            }\n            else\n            {\n                await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, state, result, cancellationToken).ConfigureAwait(false);\n                if (state.SwaggerStructure != null)\n                {\n                    shellState.ConsoleManager.WriteLine(\"Using swagger metadata from \" + result);\n                }\n                else\n                {\n                    if (state.BaseAddress == null || !Uri.TryCreate(state.BaseAddress, \"swagger/v1/swagger.json\", out result))\n                    {\n                        state.SwaggerStructure = null;\n                    }\n                    else\n                    {\n                        await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, state, result, cancellationToken).ConfigureAwait(false);\n                        if (state.SwaggerStructure != null)\n                        {\n                            shellState.ConsoleManager.WriteLine(\"Using swagger metadata from \" + result);\n                        }\n                    }\n                }\n            }\n        }\n\n        private string EnsureTrailingSlash(string v)\n        {\n            if (!v.EndsWith(\"/\", StringComparison.Ordinal))\n            {\n                v += \"/\";\n            }\n\n            return v;\n        }\n\n        public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase))\n            {\n                var helpText = new StringBuilder();\n                helpText.Append(\"Usage: \".Bold());\n                helpText.AppendLine($\"set base [uri]\");\n                helpText.AppendLine();\n                helpText.AppendLine(Description);\n                return helpText.ToString();\n            }\n\n            return null;\n        }\n\n        public string GetHelpSummary(IShellState shellState, HttpState programState)\n        {\n            return Description;\n        }\n\n        public IEnumerable<string> Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            if (parseResult.Sections.Count == 0)\n            {\n                return new[] { Name };\n            }\n\n            if (parseResult.Sections.Count > 0 && parseResult.SelectedSection == 0 && Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))\n            {\n                return new[] { Name };\n            }\n\n            if (string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 1 && (parseResult.Sections.Count < 2 || SubCommand.StartsWith(parseResult.Sections[1].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))\n            {\n                return new[] { SubCommand };\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/SetDiagCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Net.Http;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.HttpRepl.Diagnostics;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class SetDiagCommand : ICommand<HttpState, ICoreParseResult>\n    {\n        private static readonly string Name = \"set\";\n        private static readonly string SubCommand = \"diag\";\n\n        public string Description => \"Sets the diagnostics path to direct requests to.\";\n\n        public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            return parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase)\n                ? (bool?)true\n                : null;\n        }\n\n        public async Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken)\n        {\n            if (parseResult.Sections.Count == 2)\n            {\n                programState.DiagnosticsState.DiagnosticsEndpoint = null;\n                programState.DiagnosticsState.DiagnosticItems = null;\n                programState.DiagnosticsState.DiagEndpointsStructure = null;\n                return;\n            }\n\n            if (parseResult.Sections.Count != 3 || string.IsNullOrEmpty(parseResult.Sections[2]) || !Uri.TryCreate(parseResult.Sections[2], UriKind.Relative, out Uri _))\n            {\n                shellState.ConsoleManager.Error.WriteLine(\"Must specify a relative path\".SetColor(programState.ErrorColor));\n            }\n            else\n            {\n                programState.DiagnosticsState.DiagnosticsEndpoint = parseResult.Sections[2];\n                HttpResponseMessage response = await programState.Client.GetAsync(new Uri(programState.BaseAddress, programState.DiagnosticsState.DiagnosticsEndpoint), cancellationToken).ConfigureAwait(false);\n\n                if (!response.IsSuccessStatusCode)\n                {\n                    shellState.ConsoleManager.Error.WriteLine(\"Unable to access diagnostics endpoint\".SetColor(programState.ErrorColor));\n                    programState.DiagnosticsState.DiagnosticsEndpoint = null;\n                    programState.DiagnosticsState.DiagnosticItems = null;\n                }\n                else\n                {\n                    programState.DiagnosticsState.DiagnosticItems = (await response.Content.ReadAsAsync<Dictionary<string, DiagItem>>(cancellationToken).ConfigureAwait(false))?.Select(x => x.Value).ToList();\n\n                    DiagItem endpointsItem = programState.DiagnosticsState.DiagnosticItems?.FirstOrDefault(x => string.Equals(x.DisplayName, \"Endpoints\", StringComparison.OrdinalIgnoreCase));\n\n                    if (endpointsItem != null)\n                    {\n                        HttpResponseMessage endpointsResponse = await programState.Client.GetAsync(new Uri(programState.BaseAddress, endpointsItem.Url), cancellationToken).ConfigureAwait(false);\n\n                        if (!endpointsResponse.IsSuccessStatusCode)\n                        {\n                            shellState.ConsoleManager.Error.WriteLine(\"Unable to get endpoints information from diagnostics endpoint\".SetColor(programState.ErrorColor));\n                            return;\n                        }\n\n                        List<DiagEndpoint> endpoints = await endpointsResponse.Content.ReadAsAsync<List<DiagEndpoint>>(cancellationToken).ConfigureAwait(false);\n                        DirectoryStructure structure = new DirectoryStructure(null);\n\n                        foreach (DiagEndpoint endpoint in endpoints)\n                        {\n                            if (endpoint.Url.StartsWith(endpointsItem.Url, StringComparison.OrdinalIgnoreCase)\n                                || endpoint.Url.StartsWith(\"/graphql\", StringComparison.OrdinalIgnoreCase))\n                            {\n                                continue;\n                            }\n\n                            FillDirectoryInfo(structure, endpoint.Url);\n                        }\n\n                        programState.DiagnosticsState.DiagEndpointsStructure = structure;\n                    }\n                }\n            }\n        }\n\n        private static void FillDirectoryInfo(DirectoryStructure parent, string endpoint)\n        {\n            string[] parts = endpoint.Split('/');\n\n            foreach (string part in parts)\n            {\n                if (!string.IsNullOrEmpty(part))\n                {\n                    parent = parent.DeclareDirectory(part);\n                }\n            }\n        }\n\n        public string GetHelpSummary(IShellState shellState, HttpState programState)\n        {\n            return Description;\n        }\n\n        public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase))\n            {\n                return Description;\n            }\n\n            return null;\n        }\n\n        public IEnumerable<string> Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            if (parseResult.Sections.Count == 0)\n            {\n                return new[] { Name };\n            }\n\n            if (parseResult.Sections.Count > 0 && parseResult.SelectedSection == 0 && Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))\n            {\n                return new[] { Name };\n            }\n\n            if (string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 1 && (parseResult.Sections.Count < 2 || SubCommand.StartsWith(parseResult.Sections[1].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))\n            {\n                return new[] { SubCommand };\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/SetHeaderCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.HttpRepl.Suggestions;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class SetHeaderCommand : ICommand<HttpState, ICoreParseResult>\n    {\n        private static readonly string Name = \"set\";\n        private static readonly string SubCommand = \"header\";\n\n        public string Description => \"set header {name} [value] - Sets or clears a header\";\n\n        public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            return parseResult.Sections.Count > 2 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase)\n                ? (bool?)true\n                : null;\n        }\n\n        public Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken)\n        {\n            if (parseResult.Sections.Count == 3)\n            {\n                programState.Headers.Remove(parseResult.Sections[2]);\n            }\n            else\n            {\n                programState.Headers[parseResult.Sections[2]] = parseResult.Sections.Skip(3).ToList();\n            }\n\n            return Task.CompletedTask;\n        }\n\n        public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            var helpText = new StringBuilder();\n            helpText.Append(\"Usage: \".Bold());\n            helpText.AppendLine(\"set header {name} [value]\");\n            helpText.AppendLine();\n            helpText.AppendLine(\"Sets or clears a header. When [value] is empty the header is cleared.\");\n            return Description;\n        }\n\n        public string GetHelpSummary(IShellState shellState, HttpState programState)\n        {\n            return Description;\n        }\n\n        public IEnumerable<string> Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            if (parseResult.Sections.Count == 0)\n            {\n                return new[] { Name };\n            }\n\n            if (parseResult.Sections.Count > 0 && parseResult.SelectedSection == 0 && Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))\n            {\n                return new[] { Name };\n            }\n\n            if (string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 1 && (parseResult.Sections.Count < 2 || SubCommand.StartsWith(parseResult.Sections[1].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))\n            {\n                return new[] { SubCommand };\n            }\n\n            if (parseResult.Sections.Count > 2\n                && string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase)\n                && string.Equals(SubCommand, parseResult.Sections[1], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 2)\n            {\n                string prefix = parseResult.Sections[2].Substring(0, parseResult.CaretPositionWithinSelectedSection);\n                return HeaderCompletion.GetCompletions(null, prefix);\n            }\n\n            if (parseResult.Sections.Count > 3\n                && string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase)\n                && string.Equals(SubCommand, parseResult.Sections[1], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 3)\n            {\n                string prefix = parseResult.Sections[3].Substring(0, parseResult.CaretPositionWithinSelectedSection);\n                return HeaderCompletion.GetValueCompletions(null, string.Empty, parseResult.Sections[2], prefix, programState);\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Net.Http;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.HttpRepl.OpenApi;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\nusing Newtonsoft.Json;\nusing Newtonsoft.Json.Linq;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class SetSwaggerCommand : ICommand<HttpState, ICoreParseResult>\n    {\n        private static readonly string Name = \"set\";\n        private static readonly string SubCommand = \"swagger\";\n\n        public string Description => \"Sets the swagger document to use for information about the current server\";\n\n        private static void FillDirectoryInfo(DirectoryStructure parent, EndpointMetadata entry)\n        {\n            string[] parts = entry.Path.Split('/');\n\n            foreach (string part in parts)\n            {\n                if (!string.IsNullOrEmpty(part))\n                {\n                    parent = parent.DeclareDirectory(part);\n                }\n            }\n\n            RequestInfo dirRequestInfo = new RequestInfo();\n\n            foreach (KeyValuePair<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>> requestInfo in entry.AvailableRequests)\n            {\n                string method = requestInfo.Key;\n\n                foreach (KeyValuePair<string, IReadOnlyList<Parameter>> parameterSetsByContentType in requestInfo.Value)\n                {\n                    if (string.IsNullOrEmpty(parameterSetsByContentType.Key))\n                    {\n                        dirRequestInfo.SetFallbackRequestBody(method, parameterSetsByContentType.Key, GetBodyString(null, parameterSetsByContentType.Value));\n                    }\n\n                    dirRequestInfo.SetRequestBody(method, parameterSetsByContentType.Key, GetBodyString(parameterSetsByContentType.Key, parameterSetsByContentType.Value));\n                }\n\n                dirRequestInfo.AddMethod(method);\n            }\n\n            if (dirRequestInfo.Methods.Count > 0)\n            {\n                parent.RequestInfo = dirRequestInfo;\n            }\n        }\n\n        private static string GetBodyString(string contentType, IEnumerable<Parameter> operation)\n        {\n            Parameter body = operation.FirstOrDefault(x => string.Equals(x.Location, \"body\", StringComparison.OrdinalIgnoreCase));\n\n            if (body != null)\n            {\n                JToken result = GenerateData(body.Schema);\n                return result?.ToString() ?? \"{\\n}\";\n            }\n\n            return null;\n        }\n\n        private static JToken GenerateData(Schema schema)\n        {\n            if (schema == null)\n            {\n                return null;\n            }\n\n            if (schema.Example != null)\n            {\n                return JToken.FromObject(schema.Example);\n            }\n\n            if (schema.Default != null)\n            {\n                return JToken.FromObject(schema.Default);\n            }\n\n            if (schema.Type is null)\n            {\n                if (schema.Properties != null || schema.AdditionalProperties != null || schema.MinProperties.HasValue || schema.MaxProperties.HasValue)\n                {\n                    schema.Type = \"OBJECT\";\n                }\n                else if (schema.Items != null || schema.MinItems.HasValue || schema.MaxItems.HasValue)\n                {\n                    schema.Type = \"ARRAY\";\n                }\n                else if (schema.Minimum.HasValue || schema.Maximum.HasValue || schema.MultipleOf.HasValue)\n                {\n                    schema.Type = \"INTEGER\";\n                }\n            }\n\n            switch (schema.Type?.ToUpperInvariant())\n            {\n                case null:\n                case \"STRING\":\n                    return \"\";\n                case \"NUMBER\":\n                    if (schema.Minimum.HasValue)\n                    {\n                        if (schema.Maximum.HasValue)\n                        {\n                            return (schema.Maximum.Value + schema.Minimum.Value) / 2;\n                        }\n\n                        if (schema.ExclusiveMinimum)\n                        {\n                            return schema.Minimum.Value + 1;\n                        }\n\n                        return schema.Minimum.Value;\n                    }\n                    return 1.1;\n                case \"INTEGER\":\n                    if (schema.Minimum.HasValue)\n                    {\n                        if (schema.Maximum.HasValue)\n                        {\n                            return (int)((schema.Maximum.Value + schema.Minimum.Value) / 2);\n                        }\n\n                        if (schema.ExclusiveMinimum)\n                        {\n                            return schema.Minimum.Value + 1;\n                        }\n\n                        return schema.Minimum.Value;\n                    }\n                    return 0;\n                case \"BOOLEAN\":\n                    return true;\n                case \"ARRAY\":\n                    JArray container = new JArray();\n                    JToken item = GenerateData(schema.Items) ?? \"\";\n\n                    int count = schema.MinItems.GetValueOrDefault();\n                    count = Math.Max(1, count);\n\n                    for (int i = 0; i < count; ++i)\n                    {\n                        container.Add(item.DeepClone());\n                    }\n\n                    return container;\n                case \"OBJECT\":\n                    JObject obj = new JObject();\n                    foreach (KeyValuePair<string, Schema> property in schema.Properties)\n                    {\n                        JToken data = GenerateData(property.Value) ?? \"\";\n                        obj[property.Key] = data;\n                    }\n                    return obj;\n            }\n\n            return null;\n        }\n\n        private static async Task<IEnumerable<EndpointMetadata>> GetSwaggerDocAsync(HttpClient client, Uri uri)\n        {\n            var resp = await client.GetAsync(uri).ConfigureAwait(false);\n            resp.EnsureSuccessStatusCode();\n            string responseString = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);\n            JsonSerializer serializer = new JsonSerializer{ PreserveReferencesHandling = PreserveReferencesHandling.All };\n            JObject responseObject = (JObject)serializer.Deserialize(new StringReader(responseString), typeof(JObject));\n            EndpointMetadataReader reader = new EndpointMetadataReader();\n            responseObject = await PointerUtil.ResolvePointersAsync(uri, responseObject, client).ConfigureAwait(false) as JObject;\n\n            if (responseObject is null)\n            {\n                return new EndpointMetadata[0];\n            }\n\n            return reader.Read(responseObject);\n        }\n\n        public string GetHelpSummary(IShellState shellState, HttpState programState)\n        {\n            return Description;\n        }\n\n        public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase))\n            {\n                return Description;\n            }\n\n            return null;\n        }\n\n        public IEnumerable<string> Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            if (parseResult.Sections.Count == 0)\n            {\n                return new[] { Name };\n            }\n\n            if (parseResult.Sections.Count > 0 && parseResult.SelectedSection == 0 && Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))\n            {\n                return new[] { Name };\n            }\n\n            if (string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 1 && (parseResult.Sections.Count < 2 || SubCommand.StartsWith(parseResult.Sections[1].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))\n            {\n                return new[] { SubCommand };\n            }\n\n            return null;\n        }\n\n        public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            return parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase)\n                ? (bool?)true\n                : null;\n        }\n\n        public async Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken)\n        {\n            if (parseResult.Sections.Count == 2)\n            {\n                programState.SwaggerStructure = null;\n                return;\n            }\n\n            if (parseResult.Sections.Count != 3 || string.IsNullOrEmpty(parseResult.Sections[2]) || !Uri.TryCreate(parseResult.Sections[2], UriKind.Absolute, out Uri serverUri))\n            {\n                shellState.ConsoleManager.Error.WriteLine(\"Must specify a swagger document\".SetColor(programState.ErrorColor));\n            }\n            else\n            {\n                await CreateDirectoryStructureForSwaggerEndpointAsync(shellState, programState, serverUri, cancellationToken).ConfigureAwait(false);\n            }\n        }\n\n        internal static async Task CreateDirectoryStructureForSwaggerEndpointAsync(IShellState shellState, HttpState programState, Uri serverUri, CancellationToken cancellationToken)\n        {\n            programState.SwaggerEndpoint = serverUri;\n\n            try\n            {\n                IEnumerable<EndpointMetadata> doc = await GetSwaggerDocAsync(programState.Client, serverUri).ConfigureAwait(false);\n\n                DirectoryStructure d = new DirectoryStructure(null);\n\n                foreach (EndpointMetadata entry in doc)\n                {\n                    FillDirectoryInfo(d, entry);\n                }\n\n                programState.SwaggerStructure = !cancellationToken.IsCancellationRequested ? d : null;\n            }\n            catch\n            {\n                programState.SwaggerStructure = null;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/TreeNode.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class TreeNode\n    {\n        private readonly int _depth;\n        private readonly Formatter _formatter;\n        private readonly string _prefix;\n        private readonly string _entry;\n        private readonly List<TreeNode> _children = new List<TreeNode>();\n\n        public TreeNode(Formatter formatter, string prefix, string entry)\n            : this(formatter, prefix, entry, 0)\n        {\n        }\n\n        private TreeNode(Formatter formatter, string prefix, string entry, int depth)\n        {\n            _formatter = formatter;\n            formatter.RegisterEntry(prefix.Length, depth);\n            _prefix = prefix;\n            _entry = entry;\n            _depth = depth;\n        }\n\n        public TreeNode AddChild(string prefix, string entry)\n        {\n            TreeNode child = new TreeNode(_formatter, prefix, entry, _depth + 1);\n            _children.Add(child);\n            return child;\n        }\n\n        public override string ToString()\n        {\n            string self = _formatter.Format(_prefix, _entry, _depth);\n\n            if (_children.Count == 0)\n            {\n                return self;\n            }\n\n            return self + Environment.NewLine + string.Join(Environment.NewLine, _children);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Commands/UICommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Runtime.InteropServices;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.HttpRepl.Commands\n{\n    public class UICommand : ICommand<HttpState, ICoreParseResult>\n    {\n        private static readonly string Name = \"ui\";\n\n        public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            return parseResult.Sections.Count == 1 && string.Equals(parseResult.Sections[0], Name)\n                ? (bool?)true\n                : null;\n        }\n\n        public Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken)\n        {\n            if (programState.BaseAddress == null)\n            {\n                shellState.ConsoleManager.Error.WriteLine(\"Must be connected to a server to launch Swagger UI\".SetColor(programState.ErrorColor));\n                return Task.CompletedTask;\n            }\n\n            Uri uri = new Uri(programState.BaseAddress, \"swagger\");\n            string agent = \"cmd\";\n            string agentParam = $\"/c start {uri.AbsoluteUri}\";\n\n            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))\n            {\n                agent = \"open\";\n                agentParam = uri.AbsoluteUri;\n            }\n            else if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))\n            {\n                agent = \"xdg-open\";\n                agentParam = uri.AbsoluteUri;\n            }\n\n            Process.Start(new ProcessStartInfo(agent, agentParam) { CreateNoWindow = true });\n            return Task.CompletedTask;\n        }\n\n        public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            if (parseResult.Sections.Count == 1 && string.Equals(parseResult.Sections[0], Name))\n            {\n                return \"ui - Launches the Swagger UI page (if available) in the default browser\";\n            }\n\n            return null;\n        }\n\n        public string GetHelpSummary(IShellState shellState, HttpState programState)\n        {\n            return \"ui - Launches the Swagger UI page (if available) in the default browser\";\n        }\n\n        public IEnumerable<string> Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult)\n        {\n            if (parseResult.SelectedSection == 0 &&\n                (string.IsNullOrEmpty(parseResult.Sections[parseResult.SelectedSection]) || Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))\n            {\n                return new[] { Name };\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Diagnostics/ConfigItem.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.HttpRepl.Diagnostics\n{\n    public class ConfigItem\n    {\n        public string Key { get; set; }\n\n        public string Value { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Diagnostics/DiagEndpoint.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.HttpRepl.Diagnostics\n{\n    public class DiagEndpoint\n    {\n        public string DisplayName { get; set; }\n        public string Url { get; set; }\n        public DiagEndpointMetadata[] Metadata { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Diagnostics/DiagEndpointMetadata.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.HttpRepl.Diagnostics\n{\n    public class DiagEndpointMetadata\n    {\n        public object Item { get; set; }\n        public string Type { get; set; }\n        public string[] Interfaces { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Diagnostics/DiagItem.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.HttpRepl.Diagnostics\n{\n    public class DiagItem\n    {\n        public string DisplayName { get; set; }\n\n        public string Description { get; set; }\n\n        public string Url { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Diagnostics/DiagnosticsState.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.HttpRepl.Diagnostics\n{\n    public class DiagnosticsState\n    {\n        public string DiagnosticsEndpoint { get; set; }\n\n        public IReadOnlyList<DiagItem> DiagnosticItems { get; internal set; }\n\n        public IDirectoryStructure DiagEndpointsStructure { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/DirectoryStructure.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Microsoft.HttpRepl\n{\n    public class DirectoryStructure : IDirectoryStructure\n    {\n        private readonly Dictionary<string, DirectoryStructure> _childDirectories = new Dictionary<string, DirectoryStructure>(StringComparer.OrdinalIgnoreCase);\n\n        public DirectoryStructure(IDirectoryStructure parent)\n        {\n            Parent = parent;\n        }\n\n        public IEnumerable<string> DirectoryNames => _childDirectories.Keys;\n\n        public IDirectoryStructure Parent { get; }\n\n        public DirectoryStructure DeclareDirectory(string name)\n        {\n            if (_childDirectories.TryGetValue(name, out DirectoryStructure existing))\n            {\n                return existing;\n            }\n\n            return _childDirectories[name] = new DirectoryStructure(this);\n        }\n\n        public IDirectoryStructure GetChildDirectory(string name)\n        {\n            if (_childDirectories.TryGetValue(name, out DirectoryStructure result))\n            {\n                return result;\n            }\n\n            IDirectoryStructure parameterizedTarget = _childDirectories.FirstOrDefault(x => x.Key.StartsWith('{') && x.Key.EndsWith('}')).Value;\n\n            if (!(parameterizedTarget is null))\n            {\n                return parameterizedTarget;\n            }\n\n            return new DirectoryStructure(this);\n        }\n\n        public IRequestInfo RequestInfo { get; set;  }\n    }\n\n    public class RequestInfo : IRequestInfo\n    {\n        private readonly HashSet<string> _methods = new HashSet<string>(StringComparer.OrdinalIgnoreCase);\n        private readonly Dictionary<string, Dictionary<string, string>> _requestBodiesByMethodByContentType = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);\n        private readonly Dictionary<string, string> _fallbackBodyStringsByMethod = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);\n        private readonly Dictionary<string, string> _fallbackContentTypeStringsByMethod = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);\n        private readonly Dictionary<string, IReadOnlyList<string>> _contentTypesByMethod = new Dictionary<string, IReadOnlyList<string>>(StringComparer.OrdinalIgnoreCase);\n\n        public IReadOnlyList<string> Methods => _methods.ToList();\n\n        public IReadOnlyDictionary<string, IReadOnlyList<string>> ContentTypesByMethod => _contentTypesByMethod;\n\n        public string GetRequestBodyForContentType(ref string contentType, string method)\n        {\n            if (_requestBodiesByMethodByContentType.TryGetValue(method, out Dictionary<string, string> bodiesByContentType)\n                && bodiesByContentType.TryGetValue(contentType, out string body))\n            {\n                return body;\n            }\n\n            if (_fallbackBodyStringsByMethod.TryGetValue(method, out body))\n            {\n                if (_fallbackContentTypeStringsByMethod.TryGetValue(method, out string newContentType))\n                {\n                    contentType = newContentType;\n                }\n\n                return body;\n            }\n\n            return null;\n        }\n\n        public void SetRequestBody(string method, string contentType, string body)\n        {\n            if (!_requestBodiesByMethodByContentType.TryGetValue(method, out Dictionary<string, string> bodiesByContentType))\n            {\n                _requestBodiesByMethodByContentType[method] = bodiesByContentType = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);\n            }\n\n            if (!_contentTypesByMethod.TryGetValue(method, out IReadOnlyList<string> contentTypesRaw))\n            {\n                _contentTypesByMethod[method] = contentTypesRaw = new List<string>();\n            }\n\n            List<string> contentTypes = (List<string>)contentTypesRaw;\n            contentTypes.Add(contentType);\n\n            bodiesByContentType[contentType] = body;\n        }\n\n        public void AddMethod(string method)\n        {\n            _methods.Add(method);\n        }\n\n        public void SetFallbackRequestBody(string method, string contentType, string fallbackBodyString)\n        {\n            _fallbackBodyStringsByMethod[method] = fallbackBodyString;\n            _fallbackContentTypeStringsByMethod[method] = contentType;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/DirectoryStructureExtensions.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Microsoft.HttpRepl\n{\n    public static class DirectoryStructureExtensions\n    {\n        public static IEnumerable<string> GetDirectoryListingAtPath(this IDirectoryStructure structure, string path)\n        {\n            return structure.TraverseTo(path).DirectoryNames;\n        }\n\n        public static IDirectoryStructure TraverseTo(this IDirectoryStructure structure, string path)\n        {\n            string[] parts = path.Replace('\\\\', '/').Split('/');\n            return structure.TraverseTo(parts);\n        }\n\n        public static IDirectoryStructure TraverseTo(this IDirectoryStructure structure, IEnumerable<string> pathParts)\n        {\n            IDirectoryStructure s = structure;\n            IReadOnlyList<string> parts = pathParts.ToList();\n\n            if (parts.Count == 0)\n            {\n                return s;\n            }\n\n            if (parts[0] == string.Empty && parts.Count > 1)\n            {\n                while (s.Parent != null)\n                {\n                    s = s.Parent;\n                }\n            }\n\n            foreach (string part in parts)\n            {\n                if (part == \".\")\n                {\n                    continue;\n                }\n\n                if (part == \"..\")\n                {\n                    s = s.Parent ?? s;\n                }\n                else if (!string.IsNullOrEmpty(part))\n                {\n                    s = s.GetChildDirectory(part);\n                }\n            }\n\n            return s;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Formatting/JsonVisitor.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.IO;\nusing System.Text;\nusing Microsoft.HttpRepl.Preferences;\nusing Microsoft.Repl.ConsoleHandling;\nusing Newtonsoft.Json;\n\nnamespace Microsoft.HttpRepl.Formatting\n{\n    public static class JsonVisitor\n    {\n        public static string FormatAndColorize(IJsonConfig config, string jsonData)\n        {\n            if (jsonData == null)\n            {\n                return string.Empty;\n            }\n\n            StringBuilder result = new StringBuilder();\n            JsonTextReader reader = new JsonTextReader(new StringReader(jsonData));\n            bool isValuePosition = false;\n            bool isTerminalValue = false;\n            bool isFirstToken = true;\n\n            while (reader.Read())\n            {\n                if (!isValuePosition)\n                {\n                    //If we're about to write an end object/array, we shouldn't have a comma\n                    if (reader.TokenType != JsonToken.EndArray && reader.TokenType != JsonToken.EndObject\n                        && isTerminalValue)\n                    {\n                        result.Append(\",\".SetColor(config.CommaColor));\n                    }\n\n                    if (!isFirstToken)\n                    {\n                        result.AppendLine();\n                    }\n                }\n\n                isFirstToken = false;\n\n                if (!isValuePosition)\n                {\n                    result.Append(\"\".PadLeft(reader.Depth * config.IndentSize));\n                }\n\n                isTerminalValue = false;\n                isValuePosition = false;\n                JsonToken type = reader.TokenType;\n\n                switch (type)\n                {\n                    case JsonToken.StartObject:\n                        result.Append(\"{\".SetColor(config.ObjectBraceColor));\n                        break;\n                    case JsonToken.EndObject:\n                        result.Append(\"}\".SetColor(config.ObjectBraceColor));\n                        isTerminalValue = true;\n                        break;\n                    case JsonToken.StartArray:\n                        result.Append(\"[\".SetColor(config.ArrayBraceColor));\n                        break;\n                    case JsonToken.EndArray:\n                        result.Append(\"]\".SetColor(config.ArrayBraceColor));\n                        isTerminalValue = true;\n                        break;\n                    case JsonToken.PropertyName:\n                        result.Append((reader.QuoteChar.ToString() + reader.Value + reader.QuoteChar).SetColor(config.NameColor) + \": \".SetColor(config.NameSeparatorColor));\n                        isValuePosition = true;\n                        break;\n                    case JsonToken.Boolean:\n                        result.Append(reader.Value.ToString().ToLowerInvariant().SetColor(config.BoolColor));\n                        isTerminalValue = true;\n                        break;\n                    case JsonToken.Integer:\n                    case JsonToken.Float:\n                        result.Append(reader.Value.ToString().ToLowerInvariant().SetColor(config.NumericColor));\n                        isTerminalValue = true;\n                        break;\n                    case JsonToken.Null:\n                        result.Append(\"null\".SetColor(config.NullColor));\n                        isTerminalValue = true;\n                        break;\n                    case JsonToken.Comment:\n                        result.Append((\"//\" + reader.Value).SetColor(config.NumericColor));\n                        break;\n                    case JsonToken.String:\n                        result.Append((reader.QuoteChar.ToString() + reader.Value + reader.QuoteChar.ToString()).SetColor(config.StringColor));\n                        isTerminalValue = true;\n                        break;\n                    case JsonToken.Raw:\n                    case JsonToken.Date:\n                    case JsonToken.Bytes:\n                    case JsonToken.Undefined:\n                    case JsonToken.None:\n                        result.Append(reader.Value.ToString().SetColor(config.DefaultColor));\n                        isTerminalValue = true;\n                        break;\n                    case JsonToken.EndConstructor:\n                    case JsonToken.StartConstructor:\n                    default:\n                        result.Append(reader.Value.ToString().SetColor(config.DefaultColor));\n                        break;\n                }\n            }\n\n            return result.ToString();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/HttpState.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Net.Http;\nusing System.Runtime.InteropServices;\nusing Microsoft.HttpRepl.Diagnostics;\nusing Microsoft.HttpRepl.Preferences;\nusing Microsoft.Repl.ConsoleHandling;\n\nnamespace Microsoft.HttpRepl\n{\n    public class HttpState\n    {\n        private string _userProfileDir;\n        private string _prefsFilePath;\n\n        public HttpClient Client { get; }\n\n        public AllowedColors ErrorColor => this.GetColorPreference(WellKnownPreference.ErrorColor, AllowedColors.BoldRed);\n\n        public AllowedColors WarningColor => this.GetColorPreference(WellKnownPreference.WarningColor, AllowedColors.BoldYellow);\n\n        public Stack<string> PathSections { get; }\n\n        public IDirectoryStructure SwaggerStructure { get; set; }\n\n        public IDirectoryStructure Structure => DiagnosticsState.DiagEndpointsStructure == null\n            ? SwaggerStructure\n            : SwaggerStructure == null\n                ? DiagnosticsState.DiagEndpointsStructure\n                : new AggregateDirectoryStructure(SwaggerStructure, DiagnosticsState.DiagEndpointsStructure);\n\n        public Uri BaseAddress { get; set; }\n\n        public bool EchoRequest { get; set; }\n\n        public Dictionary<string, string> Preferences { get; }\n\n        public IReadOnlyDictionary<string, string> DefaultPreferences { get; }\n\n        public string UserProfileDir\n        {\n            get\n            {\n                if (_userProfileDir == null)\n                {\n                    bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);\n\n                    string profileDir = Environment.GetEnvironmentVariable(isWindows\n                        ? \"USERPROFILE\"\n                        : \"HOME\");\n\n                    _userProfileDir = profileDir;\n                }\n\n                return _userProfileDir;\n            }\n        }\n\n        public string PrefsFilePath => _prefsFilePath ?? (_prefsFilePath = Path.Combine(UserProfileDir, \".httpreplprefs\"));\n\n        public Dictionary<string, IEnumerable<string>> Headers { get; }\n\n        public DiagnosticsState DiagnosticsState { get; }\n\n        public Uri SwaggerEndpoint { get; set; }\n\n        public HttpState()\n        {\n            Client = new HttpClient();\n            PathSections = new Stack<string>();\n            Preferences = new Dictionary<string, string>();\n            DefaultPreferences = CreateDefaultPreferencs();\n            Headers = new Dictionary<string, IEnumerable<string>>(StringComparer.OrdinalIgnoreCase)\n            {\n                { \"User-Agent\", new[] { \"HTTP-REPL\" } }\n            };\n            Preferences = new Dictionary<string, string>(DefaultPreferences);\n            LoadPreferences();\n            DiagnosticsState = new DiagnosticsState();\n        }\n\n        public string GetPrompt()\n        {\n            return $\"{GetEffectivePath(new string[0], false, out int _)?.ToString() ?? \"(Disconnected)\"}~ \";\n        }\n\n        private void LoadPreferences()\n        {\n            if (File.Exists(PrefsFilePath))\n            {\n                string[] prefsFile = File.ReadAllLines(PrefsFilePath);\n\n                foreach (string line in prefsFile)\n                {\n                    int equalsIndex = line.IndexOf('=');\n\n                    if (equalsIndex < 0)\n                    {\n                        continue;\n                    }\n\n                    Preferences[line.Substring(0, equalsIndex)] = line.Substring(equalsIndex + 1);\n                }\n            }\n        }\n\n        private IReadOnlyDictionary<string, string> CreateDefaultPreferencs()\n        {\n            return new Dictionary<string, string>\n            {\n                { WellKnownPreference.ProtocolColor, \"BoldGreen\" },\n                { WellKnownPreference.StatusColor, \"BoldYellow\" },\n\n                { WellKnownPreference.JsonArrayBraceColor, \"BoldCyan\" },\n                { WellKnownPreference.JsonCommaColor, \"BoldYellow\" },\n                { WellKnownPreference.JsonNameColor, \"BoldMagenta\" },\n                { WellKnownPreference.JsonNameSeparatorColor, \"BoldWhite\" },\n                { WellKnownPreference.JsonObjectBraceColor, \"Cyan\" },\n                { WellKnownPreference.JsonColor, \"Green\" }\n            };\n        }\n\n        public bool SavePreferences()\n        {\n            List<string> lines = new List<string>();\n            foreach (KeyValuePair<string, string> entry in Preferences.OrderBy(x => x.Key))\n            {\n                //If the value didn't exist in the defaults or the value's different, include it in the user's preferences file\n                if (!DefaultPreferences.TryGetValue(entry.Key, out string value) || !string.Equals(value, entry.Value, StringComparison.Ordinal))\n                {\n                    lines.Add($\"{entry.Key}={entry.Value}\");\n                }\n            }\n\n            try\n            {\n                File.WriteAllLines(PrefsFilePath, lines);\n                return true;\n            }\n            catch\n            {\n                return false;\n            }\n        }\n\n        public string GetExampleBody(string path, ref string contentType, string method)\n        {\n            Uri effectivePath = GetEffectivePath(path);\n            string rootRelativePath = effectivePath.LocalPath.Substring(BaseAddress.LocalPath.Length).TrimStart('/');\n            IDirectoryStructure structure = SwaggerStructure?.TraverseTo(rootRelativePath);\n            return structure?.RequestInfo?.GetRequestBodyForContentType(ref contentType, method);\n        }\n\n        public IEnumerable<string> GetApplicableContentTypes(string method, string path)\n        {\n            Uri effectivePath = GetEffectivePath(path);\n            string rootRelativePath = effectivePath.LocalPath.Substring(BaseAddress.LocalPath.Length).TrimStart('/');\n            IDirectoryStructure structure = SwaggerStructure?.TraverseTo(rootRelativePath);\n            IReadOnlyDictionary<string, IReadOnlyList<string>> contentTypesByMethod = structure?.RequestInfo?.ContentTypesByMethod;\n\n            if (contentTypesByMethod != null)\n            {\n                if (method is null)\n                {\n                    return contentTypesByMethod.Values.SelectMany(x => x).Distinct(StringComparer.OrdinalIgnoreCase);\n                }\n\n                if (contentTypesByMethod.TryGetValue(method, out IReadOnlyList<string> contentTypes))\n                {\n                    return contentTypes;\n                }\n            }\n\n            return null;\n        }\n\n        public Uri GetEffectivePath(string commandSpecifiedPath)\n        {\n            if (Uri.TryCreate(commandSpecifiedPath, UriKind.Absolute, out Uri absoluteUri))\n            {\n                return absoluteUri;\n            }\n\n            UriBuilder builder = new UriBuilder(BaseAddress);\n            string path = string.Join('/', PathSections.Reverse());\n            string[] parts = path.Split('?');\n            string query = null;\n            string query2 = null;\n\n            if (parts.Length > 1)\n            {\n                path = parts[0];\n                query = string.Join('?', parts.Skip(1));\n            }\n\n            builder.Path += path;\n\n            if (commandSpecifiedPath.Length > 0)\n            {\n                if (commandSpecifiedPath[0] != '/')\n                {\n                    string argPath = commandSpecifiedPath;\n                    if (builder.Path.Length > 0 && builder.Path[builder.Path.Length - 1] != '/')\n                    {\n                        argPath = \"/\" + argPath;\n                    }\n\n                    int queryIndex = argPath.IndexOf('?');\n                    path = argPath;\n\n                    if (queryIndex > -1)\n                    {\n                        query2 = argPath.Substring(queryIndex + 1);\n                        path = argPath.Substring(0, queryIndex);\n                    }\n\n                    builder.Path += path;\n                }\n                else\n                {\n                    int queryIndex = commandSpecifiedPath.IndexOf('?');\n                    path = commandSpecifiedPath;\n\n                    if (queryIndex > -1)\n                    {\n                        query2 = commandSpecifiedPath.Substring(queryIndex + 1);\n                        path = commandSpecifiedPath.Substring(0, queryIndex);\n                    }\n\n                    builder.Path = path;\n                }\n            }\n            else\n            {\n\n                int queryIndex = commandSpecifiedPath.IndexOf('?');\n                path = commandSpecifiedPath;\n\n                if (queryIndex > -1)\n                {\n                    query2 = commandSpecifiedPath.Substring(queryIndex + 1);\n                    path = commandSpecifiedPath.Substring(0, queryIndex);\n                }\n\n                builder.Path += path;\n            }\n\n            if (query != null)\n            {\n                if (!string.IsNullOrEmpty(builder.Query))\n                {\n                    query = \"&\" + query;\n                }\n\n                builder.Query += query;\n            }\n\n            if (query2 != null)\n            {\n                if (!string.IsNullOrEmpty(builder.Query))\n                {\n                    query2 = \"&\" + query2;\n                }\n\n                builder.Query += query2;\n            }\n\n            return builder.Uri;\n        }\n\n        public Uri GetEffectivePath(IReadOnlyList<string> sections, bool requiresBody, out int filePathIndex)\n        {\n            filePathIndex = 1;\n\n            if (BaseAddress == null)\n            {\n                return null;\n            }\n\n            UriBuilder builder = new UriBuilder(BaseAddress);\n            string path = string.Join('/', PathSections.Reverse());\n            string[] parts = path.Split('?');\n            string query = null;\n            string query2 = null;\n\n            if (parts.Length > 1)\n            {\n                path = parts[0];\n                query = string.Join('?', parts.Skip(1));\n            }\n\n            builder.Path += path;\n\n            if (sections.Count > 1)\n            {\n                if (!requiresBody || !File.Exists(sections[1]))\n                {\n                    if (sections[1].Length > 0)\n                    {\n                        if (sections[1][0] != '/')\n                        {\n                            string argPath = sections[1];\n                            if (builder.Path.Length > 0 && builder.Path[builder.Path.Length - 1] != '/')\n                            {\n                                argPath = \"/\" + argPath;\n                            }\n\n                            int queryIndex = argPath.IndexOf('?');\n                            path = argPath;\n\n                            if (queryIndex > -1)\n                            {\n                                query2 = argPath.Substring(queryIndex + 1);\n                                path = argPath.Substring(0, queryIndex);\n                            }\n\n                            builder.Path += path;\n                        }\n                        else\n                        {\n                            int queryIndex = sections[1].IndexOf('?');\n                            path = sections[1];\n\n                            if (queryIndex > -1)\n                            {\n                                query2 = sections[1].Substring(queryIndex + 1);\n                                path = sections[1].Substring(0, queryIndex);\n                            }\n\n                            builder.Path = path;\n                        }\n                    }\n                    else\n                    {\n\n                        int queryIndex = sections[1].IndexOf('?');\n                        path = sections[1];\n\n                        if (queryIndex > -1)\n                        {\n                            query2 = sections[1].Substring(queryIndex + 1);\n                            path = sections[1].Substring(0, queryIndex);\n                        }\n\n                        builder.Path += path;\n                    }\n\n                    filePathIndex = 2;\n                }\n            }\n\n            if (query != null)\n            {\n                if (!string.IsNullOrEmpty(builder.Query))\n                {\n                    query = \"&\" + query;\n                }\n\n                builder.Query += query;\n            }\n\n            if (query2 != null)\n            {\n                if (!string.IsNullOrEmpty(builder.Query))\n                {\n                    query2 = \"&\" + query2;\n                }\n\n                builder.Query += query2;\n            }\n\n            return builder.Uri;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/IDirectoryStructure.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.HttpRepl\n{\n    public interface IDirectoryStructure\n    {\n        IEnumerable<string> DirectoryNames { get; }\n\n        IDirectoryStructure Parent { get; }\n\n        IDirectoryStructure GetChildDirectory(string name);\n\n        IRequestInfo RequestInfo { get; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/IRequestInfo.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.HttpRepl\n{\n    public interface IRequestInfo\n    {\n        IReadOnlyDictionary<string, IReadOnlyList<string>> ContentTypesByMethod { get; }\n\n        IReadOnlyList<string> Methods { get; }\n\n        string GetRequestBodyForContentType(ref string contentType, string method);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n    <PackAsTool>true</PackAsTool>\n    <AssemblyName>dotnet-httprepl</AssemblyName>\n    <LangVersion>latest</LangVersion>\n    <Description>Command line tool to for making HTTP calls and viewing their results.</Description>\n    <PackageTags>dotnet;http;httprepl</PackageTags>\n    <!-- This is a requirement for Microsoft tool packages only. -->\n    <PackAsToolShimRuntimeIdentifiers>win-x64;win-x86</PackAsToolShimRuntimeIdentifiers>\n\n    <!-- Temporarily disables producing this project as a package while we work through some RTM-blocking bugs. -->\n    <IsPackable>false</IsPackable>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNet.WebApi.Client\" Version=\"$(MicrosoftWebApiClientPackageVersion)\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\Microsoft.Repl\\Microsoft.Repl.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <SignedPackageFile Include=\"$(PublishDir)Microsoft.Repl.dll\" PackagePath=\"tools/$(TargetFramework)/any/Microsoft.Repl.dll\" Certificate=\"$(AssemblySigningCertName)\" />\n    <SignedPackageFile Include=\"$(PublishDir)Newtonsoft.Json.dll\" PackagePath=\"tools/$(TargetFramework)/any/Newtonsoft.Json.dll\" Certificate=\"$(AssemblySigning3rdPartyCertName)\" />\n    <SignedPackageFile Include=\"$(PublishDir)Newtonsoft.Json.Bson.dll\" PackagePath=\"tools/$(TargetFramework)/any/Newtonsoft.Json.Bson.dll\" Certificate=\"$(AssemblySigning3rdPartyCertName)\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)System.Net.Http.Formatting.dll\" PackagePath=\"tools/$(TargetFramework)/any/System.Net.Http.Formatting.dll\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/OpenApi/Either.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.HttpRepl.OpenApi\n{\n    public class Either<TOption1, TOption2>\n    {\n        public Either(TOption1 option1)\n        {\n            Option1 = option1;\n            IsOption1 = true;\n        }\n\n        public Either(TOption2 option2)\n        {\n            Option2 = option2;\n            IsOption1 = false;\n        }\n\n        public bool IsOption1 { get; }\n\n        public TOption1 Option1 { get; }\n\n        public TOption2 Option2 { get; }\n\n        public static implicit operator Either<TOption1, TOption2>(TOption1 value)\n        {\n            return new Either<TOption1, TOption2>(value);\n        }\n\n        public static implicit operator Either<TOption1, TOption2>(TOption2 value)\n        {\n            return new Either<TOption1, TOption2>(value);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/OpenApi/EitherConverter.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Newtonsoft.Json;\n\nnamespace Microsoft.HttpRepl.OpenApi\n{\n    public class EitherConverter<TOption1, TOption2> : JsonConverter\n    {\n        public override bool CanConvert(Type objectType)\n        {\n            return typeof(TOption1).IsAssignableFrom(objectType) || typeof(TOption2).IsAssignableFrom(objectType) || typeof(EitherConverter<TOption1, TOption2>) == objectType;\n        }\n\n        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)\n        {\n            try\n            {\n                TOption1 option1 = serializer.Deserialize<TOption1>(reader);\n                return new Either<TOption1, TOption2>(option1);\n            }\n            catch\n            {\n                TOption2 option2 = serializer.Deserialize<TOption2>(reader);\n                return new Either<TOption1, TOption2>(option2);\n            }\n        }\n\n        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)\n        {\n            throw new NotImplementedException();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/OpenApi/EndpointMetadata.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.HttpRepl.OpenApi\n{\n    public class EndpointMetadata\n    {\n        public EndpointMetadata(string path, IReadOnlyDictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>> requestsByMethodAndContentType)\n        {\n            Path = path;\n            AvailableRequests = requestsByMethodAndContentType ?? new Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>>();\n        }\n\n        public string Path { get; }\n\n        public IReadOnlyDictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>> AvailableRequests { get; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/OpenApi/EndpointMetadataReader.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing Newtonsoft.Json.Linq;\n\nnamespace Microsoft.HttpRepl.OpenApi\n{\n    public class EndpointMetadataReader\n    {\n        private readonly List<IEndpointMetadataReader> _readers = new List<IEndpointMetadataReader>\n        {\n            new OpenApiV3EndpointMetadataReader(),\n            new SwaggerV2EndpointMetadataReader(),\n            new SwaggerV1EndpointMetadataReader()\n        };\n\n        public void RegisterReader(IEndpointMetadataReader reader)\n        {\n            _readers.Add(reader);\n        }\n\n        public IEnumerable<EndpointMetadata> Read(JObject document)\n        {\n            foreach (IEndpointMetadataReader reader in _readers)\n            {\n                if (reader.CanHandle(document))\n                {\n                    IEnumerable<EndpointMetadata> result = reader.ReadMetadata(document);\n\n                    if (result != null)\n                    {\n                        return result;\n                    }\n                }\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/OpenApi/IEndpointMetadataReader.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing Newtonsoft.Json.Linq;\n\nnamespace Microsoft.HttpRepl.OpenApi\n{\n    public interface IEndpointMetadataReader\n    {\n        bool CanHandle(JObject document);\n\n        IEnumerable<EndpointMetadata> ReadMetadata(JObject document);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/OpenApi/OpenApiV3EndpointMetadataReader.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Newtonsoft.Json.Linq;\n\nnamespace Microsoft.HttpRepl.OpenApi\n{\n    public class OpenApiV3EndpointMetadataReader : IEndpointMetadataReader\n    {\n        public bool CanHandle(JObject document)\n        {\n            return (document[\"openapi\"]?.ToString() ?? \"\").StartsWith(\"3.\", StringComparison.Ordinal);\n        }\n\n        public IEnumerable<EndpointMetadata> ReadMetadata(JObject document)\n        {\n            List<EndpointMetadata> metadata = new List<EndpointMetadata>();\n\n            if (document[\"paths\"] is JObject paths)\n            {\n                foreach (JProperty path in paths.Properties())\n                {\n                    if (!(path.Value is JObject pathBody))\n                    {\n                        continue;\n                    }\n\n                    Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>> requestMethods = new Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>>(StringComparer.OrdinalIgnoreCase);\n\n                    foreach (JProperty method in pathBody.Properties())\n                    {\n                        List<Parameter> parameters = new List<Parameter>();\n\n                        if (method.Value is JObject methodBody)\n                        {\n                            if (methodBody[\"parameters\"] is JArray parametersArray)\n                            {\n                                foreach (JObject parameterObj in parametersArray.OfType<JObject>())\n                                {\n                                    Parameter p = parameterObj.ToObject<Parameter>();\n                                    p.Location = parameterObj[\"in\"]?.ToString();\n\n                                    if (!(parameterObj[\"schema\"] is JObject schemaObject))\n                                    {\n                                        schemaObject = null;\n                                    }\n\n                                    p.Schema = schemaObject?.ToObject<Schema>() ?? parameterObj.ToObject<Schema>();\n                                    parameters.Add(p);\n                                }\n                            }\n\n                            if (methodBody[\"requestBody\"] is JObject bodyObject)\n                            {\n                                if (!(bodyObject[\"content\"] is JObject contentTypeLookup))\n                                {\n                                    continue;\n                                }\n\n                                foreach (JProperty contentTypeEntry in contentTypeLookup.Properties())\n                                {\n                                    List<Parameter> parametersByContentType = new List<Parameter>(parameters);\n                                    Parameter p = bodyObject.ToObject<Parameter>();\n                                    p.Location = \"body\";\n                                    p.IsRequired = bodyObject[\"required\"]?.ToObject<bool>() ?? false;\n\n                                    if (!(bodyObject[\"schema\"] is JObject schemaObject))\n                                    {\n                                        schemaObject = null;\n                                    }\n\n                                    p.Schema = schemaObject?.ToObject<Schema>() ?? bodyObject.ToObject<Schema>();\n                                    parametersByContentType.Add(p);\n\n                                    Dictionary<string, IReadOnlyList<Parameter>> bucketByMethod;\n                                    if (!requestMethods.TryGetValue(method.Name, out IReadOnlyDictionary<string, IReadOnlyList<Parameter>> bucketByMethodRaw))\n                                    {\n                                        requestMethods[method.Name] = bucketByMethodRaw = new Dictionary<string, IReadOnlyList<Parameter>>(StringComparer.OrdinalIgnoreCase)\n                                        {\n                                            { \"\", parametersByContentType }\n                                        };\n                                    }\n\n                                    bucketByMethod = (Dictionary<string, IReadOnlyList<Parameter>>)bucketByMethodRaw;\n                                    bucketByMethod[contentTypeEntry.Name] = parametersByContentType;\n                                }\n                            }\n                        }\n                    }\n\n                    metadata.Add(new EndpointMetadata(path.Name, requestMethods));\n                }\n            }\n\n            return metadata;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/OpenApi/Parameter.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.HttpRepl.OpenApi\n{\n    public class Parameter\n    {\n        public string Name { get; set; }\n\n        public string Location { get; set; }\n\n        public bool IsRequired { get; set; }\n\n        public Schema Schema { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Net.Http;\nusing System.Threading.Tasks;\nusing Newtonsoft.Json.Linq;\n\nnamespace Microsoft.HttpRepl.OpenApi\n{\n    public static class PointerUtil\n    {\n        public static Task<JToken> ResolvePointersAsync(Uri loadLocation, JToken root, HttpClient client)\n        {\n            return ResolvePointersAsync(loadLocation, root, root, client);\n        }\n\n        private static async Task<JToken> ResolvePointersAsync(Uri loadLocation, JToken root, JToken toResolve, HttpClient client)\n        {\n            JToken cursor = root;\n\n            if (toResolve is JArray arr)\n            {\n                for (int i = 0; i < arr.Count; ++i)\n                {\n                    arr[i] = await ResolvePointersAsync(loadLocation, root, arr[i], client).ConfigureAwait(false);\n                }\n            }\n            else if (toResolve is JObject obj)\n            {\n                if (obj[\"$ref\"] is JValue refVal && refVal.Type == JTokenType.String)\n                {\n                    if (!Uri.TryCreate((string)refVal.Value, UriKind.RelativeOrAbsolute, out Uri loadTarget))\n                    {\n                        //TODO: Error resolving pointer (pointer must be a valid URI)\n                        return new JValue((object)null);\n                    }\n                    \n                    if (!loadTarget.IsAbsoluteUri)\n                    {\n                        if (!Uri.TryCreate(loadLocation, loadTarget, out loadTarget))\n                        {\n                            //TODO: Error resolving pointer (could not combine with base path)\n                            return new JValue((object)null);\n                        }\n                    }\n\n                    //Check to see if we're changing source documents, if we are, get it\n                    if (!string.Equals(loadLocation.Host, loadTarget.Host, StringComparison.OrdinalIgnoreCase) || !string.Equals(loadLocation.AbsolutePath, loadTarget.AbsolutePath, StringComparison.OrdinalIgnoreCase))\n                    {\n                        HttpResponseMessage responseMessage = await client.GetAsync(loadTarget).ConfigureAwait(false);\n\n                        if (!responseMessage.IsSuccessStatusCode)\n                        {\n                            //TODO: Error resolving pointer (could not get referenced document)\n                            return new JValue((object)null);\n                        }\n\n                        string responseString = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);\n                        JToken newRoot;\n\n                        try\n                        {\n                            newRoot = JToken.Parse(responseString);\n                        }\n                        catch\n                        {\n                            //TODO: Error resolving pointer (referenced document is not valid JSON)\n                            return new JValue((object)null);\n                        }\n\n                        cursor = await ResolvePointersAsync(loadTarget, newRoot, newRoot, client).ConfigureAwait(false);\n                    }\n\n                    //We're in the right document, grab the bookmark (fragment) of the URI and get the element at that path\n                    string fragment = loadTarget.Fragment;\n\n                    if (fragment.StartsWith('#'))\n                    {\n                        fragment = fragment.Substring(1);\n                    }\n\n                    string[] parts = fragment.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);\n\n                    for (int i = 0; i < parts.Length; ++i)\n                    {\n                        if (cursor is JArray ca)\n                        {\n                            if (!int.TryParse(parts[i], NumberStyles.Integer, CultureInfo.InvariantCulture, out int index))\n                            {\n                                //TODO: Error resolving pointer, array index is non-integral\n                                return new JValue((object)null);\n                            }\n\n                            if (index < 0 || index >= ca.Count)\n                            {\n                                //TODO: Error resolving pointer, array index is out of bounds\n                                return new JValue((object)null);\n                            }\n\n                            JToken val = ca[index];\n                            if (val is JObject vo && vo.TryGetValue(\"$ref\", out JToken vor) && vor is JValue vorv && vorv.Type == JTokenType.String)\n                            {\n                                cursor = await ResolvePointersAsync(loadLocation, root, val, client).ConfigureAwait(false);\n                            }\n                            else\n                            {\n                                cursor = val;\n                            }\n                        }\n                        else if (cursor is JObject co)\n                        {\n                            if (!co.TryGetValue(parts[i], out JToken val))\n                            {\n                                //TODO: Error resolving pointer, no such property on object\n                                return new JValue((object)null);\n                            }\n\n                            if (val is JObject vo && vo.TryGetValue(\"$ref\", out JToken vor) && vor is JValue vorv && vorv.Type == JTokenType.String)\n                            {\n                                cursor = await ResolvePointersAsync(loadLocation, root, val, client).ConfigureAwait(false);\n                            }\n                            else\n                            {\n                                cursor = val;\n                            }\n                        }\n                        else\n                        {\n                            //TODO: Error resolving pointer, cannot index into literal\n                            return new JValue((object)null);\n                        }\n                    }\n\n                    cursor = await ResolvePointersAsync(loadLocation, root, cursor, client);\n                    return cursor.DeepClone();\n                }\n\n                foreach (JProperty property in obj.Properties().ToList())\n                {\n                    obj[property.Name] = await ResolvePointersAsync(loadLocation, root, property.Value, client).ConfigureAwait(false);\n                }\n            }\n\n            return toResolve;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/OpenApi/Schema.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing System.Linq;\nusing Newtonsoft.Json;\nusing Newtonsoft.Json.Linq;\n\nnamespace Microsoft.HttpRepl.OpenApi\n{\n    public class Schema\n    {\n        public void PrepareForUsage(JToken document)\n        {\n            AdditionalProperties?.Option1?.PrepareForUsage(document);\n\n            if (AllOf != null)\n            {\n                for (int i = 0; i < AllOf.Length; ++i)\n                {\n                    AllOf[i].PrepareForUsage(document);\n                }\n            }\n\n            if (AnyOf != null)\n            {\n                for (int i = 0; i < AnyOf.Length; ++i)\n                {\n                    AnyOf[i].PrepareForUsage(document);\n                }\n            }\n\n            if (OneOf != null)\n            {\n                for (int i = 0; i < OneOf.Length; ++i)\n                {\n                    OneOf[i].PrepareForUsage(document);\n                }\n            }\n\n            if (Properties != null)\n            {\n                IReadOnlyList<string> keys = Properties.Keys.ToList();\n                for (int i = 0; i < keys.Count; ++i)\n                {\n                    Properties[keys[i]]?.PrepareForUsage(document);\n                }\n            }\n\n            Items?.PrepareForUsage(document);\n            Not?.PrepareForUsage(document);\n\n            if (Required?.Option1 != null)\n            {\n                if (Properties != null)\n                {\n                    foreach (string propertyName in Required.Option1)\n                    {\n                        if (Properties.TryGetValue(propertyName, out Schema value))\n                        {\n                            value.Required = true;\n                        }\n                    }\n                }\n\n                Required = false;\n            }\n        }\n\n        [JsonConverter(typeof(EitherConverter<Schema, bool>))]\n        public Either<Schema, bool> AdditionalProperties { get; set; }\n\n        public Schema[] AllOf { get; set; }\n\n        public Schema[] AnyOf { get; set; }\n\n        public object Default { get; set; }\n\n        public string Description { get; set; }\n\n        public object[] Enum { get; set; }\n\n        public object Example { get; set; }\n\n        public bool ExclusiveMaximum { get; set; }\n\n        public bool ExclusiveMinimum { get; set; }\n\n        public string Format { get; set; }\n\n        public Schema Items { get; set; }\n\n        public double? Maximum { get; set; }\n\n        public double? Minimum { get; set; }\n\n        public int? MaxItems { get; set; }\n\n        public int? MinItems { get; set; }\n\n        public int? MaxLength { get; set; }\n\n        public int? MinLength { get; set; }\n\n        public int? MaxProperties { get; set; }\n\n        public int? MinProperties { get; set; }\n\n        public double? MultipleOf { get; set; }\n\n        public Schema Not { get; set; }\n\n        public Schema[] OneOf { get; set; }\n\n        public string Pattern { get; set; }\n\n        public Dictionary<string, Schema> Properties { get; set; }\n\n        [JsonConverter(typeof(EitherConverter<string[], bool>))]\n        public Either<string[], bool> Required { get; set; }\n\n        public string Title { get; set; }\n\n        public string Type { get; set; }\n\n        public bool UniqueItems { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/OpenApi/SwaggerV1EndpointMetadataReader.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Newtonsoft.Json.Linq;\n\nnamespace Microsoft.HttpRepl.OpenApi\n{\n    public class SwaggerV1EndpointMetadataReader : IEndpointMetadataReader\n    {\n        public bool CanHandle(JObject document)\n        {\n            return (document[\"swaggerVersion\"]?.ToString() ?? \"\").StartsWith(\"1.\", StringComparison.Ordinal);\n        }\n\n        public IEnumerable<EndpointMetadata> ReadMetadata(JObject document)\n        {\n            List<EndpointMetadata> metadata = new List<EndpointMetadata>();\n\n            if (!(document[\"consumes\"] is JArray globalConsumes))\n            {\n                globalConsumes = new JArray();\n            }\n\n            if (document[\"apis\"] is JObject obj)\n            {\n                foreach (JProperty property in obj.Properties())\n                {\n                    string path = obj[\"path\"]?.ToString();\n\n                    if (path is null)\n                    {\n                        continue;\n                    }\n\n                    Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>> requestMethods = new Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>>(StringComparer.Ordinal);\n\n                    if (obj[\"operations\"] is JArray operations)\n                    {\n                        foreach (JObject operationObject in operations.OfType<JObject>())\n                        {\n                            string method = operationObject[\"method\"]?.ToString();\n                            List<Parameter> parameters = new List<Parameter>();\n\n                            if (operationObject[\"parameters\"] is JArray parametersArray)\n                            {\n                                foreach (JObject parameterObj in parametersArray.OfType<JObject>())\n                                {\n                                    Parameter p = parameterObj.ToObject<Parameter>();\n                                    p.Location = parameterObj[\"paramType\"]?.ToString();\n                                    p.IsRequired = parameterObj[\"required\"]?.ToObject<bool>() ?? false;\n\n                                    string type = parameterObj[\"type\"]?.ToString();\n\n                                    if (type is null)\n                                    {\n                                        continue;\n                                    }\n\n                                    switch (type.ToUpperInvariant())\n                                    {\n                                        case \"INTEGER\":\n                                        case \"NUMBER\":\n                                        case \"STRING\":\n                                        case \"BOOLEAN\":\n                                            p.Schema = new Schema { Type = type };\n                                            break;\n                                        case \"FILE\":\n                                            break;\n                                        default:\n                                            if (document[\"models\"]?[type] is JObject schemaObject)\n                                            {\n                                                //TODO: Handle subtypes (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/1.2.md#527-model-object)\n                                                p.Schema = schemaObject.ToObject<Schema>();\n                                            }\n                                            break;\n                                    }\n\n                                    parameters.Add(p);\n                                }\n                            }\n\n                            if (!(operationObject[\"consumes\"] is JArray consumes))\n                            {\n                                consumes = globalConsumes;\n                            }\n\n                            Dictionary<string, IReadOnlyList<Parameter>> parametersByContentType = new Dictionary<string, IReadOnlyList<Parameter>>(StringComparer.OrdinalIgnoreCase)\n                            {\n                                { \"\", parameters }\n                            };\n\n                            foreach (JValue value in consumes.OfType<JValue>().Where(x => x.Type == JTokenType.String))\n                            {\n                                parametersByContentType[value.ToString()] = parameters;\n                            }\n                        }\n                    }\n\n                    metadata.Add(new EndpointMetadata(path, requestMethods));\n                }\n            }\n\n            return metadata;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/OpenApi/SwaggerV2EndpointMetadataReader.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Newtonsoft.Json.Linq;\n\nnamespace Microsoft.HttpRepl.OpenApi\n{\n    public class SwaggerV2EndpointMetadataReader : IEndpointMetadataReader\n    {\n        public bool CanHandle(JObject document)\n        {\n            return (document[\"swagger\"]?.ToString() ?? \"\").StartsWith(\"2.\", StringComparison.Ordinal);\n        }\n\n        public IEnumerable<EndpointMetadata> ReadMetadata(JObject document)\n        {\n            List<EndpointMetadata> metadata = new List<EndpointMetadata>();\n\n            if (!(document[\"consumes\"] is JArray globalConsumes))\n            {\n                globalConsumes = new JArray();\n            }\n\n            if (document[\"paths\"] is JObject obj)\n            {\n                foreach (JProperty property in obj.Properties())\n                {\n                    if (!(property.Value is JObject requestMethodInfos))\n                    {\n                        continue;\n                    }\n\n                    Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>> requestMethods = new Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>>(StringComparer.Ordinal);\n\n                    foreach (JProperty methodInfo in requestMethodInfos.Properties())\n                    {\n                        List<Parameter> parameters = new List<Parameter>();\n\n                        if (methodInfo.Value is JObject methodInfoDescription)\n                        {\n                            if (methodInfoDescription[\"parameters\"] is JArray parametersArray)\n                            {\n                                foreach (JObject parameterObj in parametersArray.OfType<JObject>())\n                                {\n                                    //TODO: Resolve refs here\n\n                                    Parameter p = parameterObj.ToObject<Parameter>();\n                                    p.Location = parameterObj[\"in\"]?.ToString();\n                                    p.IsRequired = parameterObj[\"required\"]?.ToObject<bool>() ?? false;\n\n                                    if (!(parameterObj[\"schema\"] is JObject schemaObject))\n                                    {\n                                        schemaObject = null;\n                                    }\n\n                                    p.Schema = schemaObject?.ToObject<Schema>() ?? parameterObj.ToObject<Schema>();\n                                    parameters.Add(p);\n                                }\n                            }\n\n                            if (!(methodInfoDescription[\"consumes\"] is JArray consumes))\n                            {\n                                consumes = globalConsumes;\n                            }\n\n                            Dictionary<string, IReadOnlyList<Parameter>> parametersByContentType = new Dictionary<string, IReadOnlyList<Parameter>>(StringComparer.OrdinalIgnoreCase)\n                            {\n                                { \"\", parameters }\n                            };\n\n                            foreach (JValue value in consumes.OfType<JValue>().Where(x => x.Type == JTokenType.String))\n                            {\n                                parametersByContentType[value.ToString()] = parameters;\n                            }\n\n                            requestMethods[methodInfo.Name] = parametersByContentType;\n                        }\n                    }\n\n                    metadata.Add(new EndpointMetadata(property.Name, requestMethods));\n                }\n            }\n\n            return metadata;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Preferences/IJsonConfig.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.Repl.ConsoleHandling;\n\nnamespace Microsoft.HttpRepl.Preferences\n{\n    public interface IJsonConfig\n    {\n        int IndentSize { get; }\n\n        AllowedColors DefaultColor { get; }\n\n        AllowedColors ArrayBraceColor { get; }\n\n        AllowedColors ObjectBraceColor { get; }\n\n        AllowedColors CommaColor { get; }\n\n        AllowedColors NameColor { get; }\n\n        AllowedColors NameSeparatorColor { get; }\n\n        AllowedColors BoolColor { get; }\n\n        AllowedColors NumericColor { get; }\n\n        AllowedColors StringColor { get; }\n\n        AllowedColors NullColor { get; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Preferences/JsonConfig.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.Repl.ConsoleHandling;\n\nnamespace Microsoft.HttpRepl.Preferences\n{\n    public class JsonConfig : IJsonConfig\n    {\n        private readonly HttpState _state;\n\n        public int IndentSize => _state.GetIntPreference(WellKnownPreference.JsonIndentSize, 2);\n\n        public AllowedColors DefaultColor => _state.GetColorPreference(WellKnownPreference.JsonColor);\n\n        private AllowedColors DefaultBraceColor => _state.GetColorPreference(WellKnownPreference.JsonBraceColor, DefaultSyntaxColor);\n\n        private AllowedColors DefaultSyntaxColor => _state.GetColorPreference(WellKnownPreference.JsonSyntaxColor, DefaultColor);\n\n        private AllowedColors DefaultLiteralColor => _state.GetColorPreference(WellKnownPreference.JsonLiteralColor, DefaultColor);\n\n        public AllowedColors ArrayBraceColor => _state.GetColorPreference(WellKnownPreference.JsonArrayBraceColor, DefaultBraceColor);\n\n        public AllowedColors ObjectBraceColor => _state.GetColorPreference(WellKnownPreference.JsonObjectBraceColor, DefaultBraceColor);\n\n        public AllowedColors CommaColor => _state.GetColorPreference(WellKnownPreference.JsonCommaColor, DefaultSyntaxColor);\n\n        public AllowedColors NameColor => _state.GetColorPreference(WellKnownPreference.JsonNameColor, StringColor);\n\n        public AllowedColors NameSeparatorColor => _state.GetColorPreference(WellKnownPreference.JsonNameSeparatorColor, DefaultSyntaxColor);\n\n        public AllowedColors BoolColor => _state.GetColorPreference(WellKnownPreference.JsonBoolColor, DefaultLiteralColor);\n\n        public AllowedColors NumericColor => _state.GetColorPreference(WellKnownPreference.JsonNumericColor, DefaultLiteralColor);\n\n        public AllowedColors StringColor => _state.GetColorPreference(WellKnownPreference.JsonStringColor, DefaultLiteralColor);\n\n        public AllowedColors NullColor => _state.GetColorPreference(WellKnownPreference.JsonNullColor, DefaultLiteralColor);\n\n        public JsonConfig(HttpState state)\n        {\n            _state = state;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Preferences/RequestConfig.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.Repl.ConsoleHandling;\n\nnamespace Microsoft.HttpRepl.Preferences\n{\n    public class RequestConfig : RequestOrResponseConfig\n    {\n        public RequestConfig(HttpState state)\n            : base(state)\n        {\n        }\n\n        public override AllowedColors BodyColor => State.GetColorPreference(WellKnownPreference.RequestBodyColor, base.BodyColor);\n\n        public override AllowedColors SchemeColor => State.GetColorPreference(WellKnownPreference.RequestSchemeColor, base.SchemeColor);\n\n        public override AllowedColors HeaderKeyColor => State.GetColorPreference(WellKnownPreference.RequestHeaderKeyColor, base.HeaderKeyColor);\n\n        public override AllowedColors HeaderSeparatorColor => State.GetColorPreference(WellKnownPreference.RequestHeaderSeparatorColor, base.HeaderSeparatorColor);\n\n        public override AllowedColors HeaderValueSeparatorColor => State.GetColorPreference(WellKnownPreference.RequestHeaderValueSeparatorColor, base.HeaderValueSeparatorColor);\n\n        public override AllowedColors HeaderValueColor => State.GetColorPreference(WellKnownPreference.RequestHeaderValueColor, base.HeaderValueColor);\n\n        public override AllowedColors HeaderColor => State.GetColorPreference(WellKnownPreference.RequestHeaderColor, base.HeaderColor);\n\n        public override AllowedColors GeneralColor => State.GetColorPreference(WellKnownPreference.RequestColor, base.GeneralColor);\n\n        public override AllowedColors ProtocolColor => State.GetColorPreference(WellKnownPreference.RequestProtocolColor, base.ProtocolColor);\n\n        public override AllowedColors ProtocolNameColor => State.GetColorPreference(WellKnownPreference.RequestProtocolNameColor, base.ProtocolNameColor);\n\n        public override AllowedColors ProtocolVersionColor => State.GetColorPreference(WellKnownPreference.RequestProtocolVersionColor, base.ProtocolVersionColor);\n\n        public override AllowedColors ProtocolSeparatorColor => State.GetColorPreference(WellKnownPreference.RequestProtocolSeparatorColor, base.ProtocolSeparatorColor);\n\n        public override AllowedColors StatusColor => State.GetColorPreference(WellKnownPreference.RequestStatusColor, base.StatusColor);\n\n        public override AllowedColors StatusCodeColor => State.GetColorPreference(WellKnownPreference.RequestStatusCodeColor, base.StatusCodeColor);\n\n        public override AllowedColors StatusReasonPhraseColor => State.GetColorPreference(WellKnownPreference.RequestStatusReaseonPhraseColor, base.StatusReasonPhraseColor);\n\n        public AllowedColors MethodColor => State.GetColorPreference(WellKnownPreference.RequestMethodColor, GeneralColor);\n\n        public AllowedColors AddressColor => State.GetColorPreference(WellKnownPreference.RequestAddressColor, GeneralColor);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Preferences/RequestOrResponseConfig.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.Repl.ConsoleHandling;\n\nnamespace Microsoft.HttpRepl.Preferences\n{\n    public abstract class RequestOrResponseConfig\n    {\n        protected HttpState State { get; }\n\n        protected RequestOrResponseConfig(HttpState state)\n        {\n            State = state;\n        }\n\n        public virtual AllowedColors BodyColor => State.GetColorPreference(WellKnownPreference.BodyColor, GeneralColor);\n\n        public virtual AllowedColors SchemeColor => State.GetColorPreference(WellKnownPreference.SchemeColor, GeneralColor);\n\n        public virtual AllowedColors HeaderKeyColor => State.GetColorPreference(WellKnownPreference.HeaderKeyColor, HeaderColor);\n\n        public virtual AllowedColors HeaderSeparatorColor => State.GetColorPreference(WellKnownPreference.HeaderSeparatorColor, HeaderColor);\n\n        public virtual AllowedColors HeaderValueSeparatorColor => State.GetColorPreference(WellKnownPreference.HeaderValueSeparatorColor, HeaderSeparatorColor);\n\n        public virtual AllowedColors HeaderValueColor => State.GetColorPreference(WellKnownPreference.HeaderValueColor, HeaderColor);\n\n        public virtual AllowedColors HeaderColor => State.GetColorPreference(WellKnownPreference.HeaderColor, GeneralColor);\n\n        public virtual AllowedColors GeneralColor => State.GetColorPreference(WellKnownPreference.RequestOrResponseColor);\n\n        public virtual AllowedColors ProtocolColor => State.GetColorPreference(WellKnownPreference.ProtocolColor, GeneralColor);\n\n        public virtual AllowedColors ProtocolNameColor => State.GetColorPreference(WellKnownPreference.ProtocolNameColor, ProtocolColor);\n\n        public virtual AllowedColors ProtocolVersionColor => State.GetColorPreference(WellKnownPreference.ProtocolVersionColor, ProtocolColor);\n\n        public virtual AllowedColors ProtocolSeparatorColor => State.GetColorPreference(WellKnownPreference.ProtocolSeparatorColor, ProtocolColor);\n\n        public virtual AllowedColors StatusColor => State.GetColorPreference(WellKnownPreference.StatusColor, GeneralColor);\n\n        public virtual AllowedColors StatusCodeColor => State.GetColorPreference(WellKnownPreference.StatusCodeColor, StatusColor);\n\n        public virtual AllowedColors StatusReasonPhraseColor => State.GetColorPreference(WellKnownPreference.StatusReaseonPhraseColor, StatusColor);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Preferences/ResponseConfig.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.Repl.ConsoleHandling;\n\nnamespace Microsoft.HttpRepl.Preferences\n{\n    public class ResponseConfig : RequestOrResponseConfig\n    {\n        public ResponseConfig(HttpState state)\n            : base(state)\n        {\n        }\n\n        public override AllowedColors BodyColor => State.GetColorPreference(WellKnownPreference.ResponseBodyColor, base.BodyColor);\n\n        public override AllowedColors SchemeColor => State.GetColorPreference(WellKnownPreference.ResponseSchemeColor, base.SchemeColor);\n\n        public override AllowedColors HeaderKeyColor => State.GetColorPreference(WellKnownPreference.ResponseHeaderKeyColor, base.HeaderKeyColor);\n\n        public override AllowedColors HeaderSeparatorColor => State.GetColorPreference(WellKnownPreference.ResponseHeaderSeparatorColor, base.HeaderSeparatorColor);\n\n        public override AllowedColors HeaderValueSeparatorColor => State.GetColorPreference(WellKnownPreference.ResponseHeaderValueSeparatorColor, base.HeaderValueSeparatorColor);\n\n        public override AllowedColors HeaderValueColor => State.GetColorPreference(WellKnownPreference.ResponseHeaderValueColor, base.HeaderValueColor);\n\n        public override AllowedColors HeaderColor => State.GetColorPreference(WellKnownPreference.ResponseHeaderColor, base.HeaderColor);\n\n        public override AllowedColors GeneralColor => State.GetColorPreference(WellKnownPreference.ResponseColor, base.GeneralColor);\n\n        public override AllowedColors ProtocolColor => State.GetColorPreference(WellKnownPreference.ResponseProtocolColor, base.ProtocolColor);\n\n        public override AllowedColors ProtocolNameColor => State.GetColorPreference(WellKnownPreference.ResponseProtocolNameColor, base.ProtocolNameColor);\n\n        public override AllowedColors ProtocolVersionColor => State.GetColorPreference(WellKnownPreference.ResponseProtocolVersionColor, base.ProtocolVersionColor);\n\n        public override AllowedColors ProtocolSeparatorColor => State.GetColorPreference(WellKnownPreference.ResponseProtocolSeparatorColor, base.ProtocolSeparatorColor);\n\n        public override AllowedColors StatusColor => State.GetColorPreference(WellKnownPreference.ResponseStatusColor, base.StatusColor);\n\n        public override AllowedColors StatusCodeColor => State.GetColorPreference(WellKnownPreference.ResponseStatusCodeColor, base.StatusCodeColor);\n\n        public override AllowedColors StatusReasonPhraseColor => State.GetColorPreference(WellKnownPreference.ResponseStatusReaseonPhraseColor, base.StatusReasonPhraseColor);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing Microsoft.Repl.ConsoleHandling;\n\nnamespace Microsoft.HttpRepl.Preferences\n{\n    public static class WellKnownPreference\n    {\n        public static class Catalog\n        {\n            private static IReadOnlyList<string> _names;\n\n            public static IReadOnlyList<string> Names\n            {\n                get\n                {\n                    if (_names != null)\n                    {\n                        return _names;\n                    }\n\n                    List<string> matchingProperties = new List<string>();\n\n                    foreach (PropertyInfo property in typeof(WellKnownPreference).GetProperties(BindingFlags.Public | BindingFlags.Static))\n                    {\n                        if (property.PropertyType == typeof(string) && property.GetMethod != null && property.GetValue(null) is string val)\n                        {\n                            matchingProperties.Add(val);\n                        }\n                    }\n\n                    return _names = matchingProperties;\n                }\n            }\n        }\n\n        public static string JsonArrayBraceColor { get; } = \"colors.json.arrayBrace\";\n\n        public static string JsonObjectBraceColor { get; } = \"colors.json.objectBrace\";\n\n        public static string JsonNameColor { get; } = \"colors.json.name\";\n\n        public static string JsonNameSeparatorColor { get; } = \"colors.json.nameSeparator\";\n\n        public static string JsonIndentSize { get; } = \"formatting.json.indentSize\";\n\n        public static string JsonCommaColor { get; } = \"colors.json.comma\";\n\n        public static string JsonLiteralColor { get; } = \"colors.json.literal\";\n\n        public static string JsonNullColor { get; } = \"colors.json.null\";\n\n        public static string JsonBoolColor { get; } = \"colors.json.bool\";\n\n        public static string JsonNumericColor { get; } = \"colors.json.numeric\";\n\n        public static string JsonStringColor { get; } = \"colors.json.string\";\n\n        public static string JsonColor { get; } = \"colors.json\";\n\n        public static string JsonSyntaxColor { get; } = \"colors.json.syntax\";\n\n        public static string JsonBraceColor { get; } = \"colors.json.brace\";\n\n        public static string RequestColor { get; } = \"colors.request\";\n\n        public static string RequestBodyColor { get; } = \"colors.request.body\";\n\n        public static string RequestSchemeColor { get; } = \"colors.request.scheme\";\n\n        public static string RequestHeaderKeyColor { get; } = \"colors.request.header.key\";\n\n        public static string RequestHeaderSeparatorColor { get; } = \"colors.request.header.separator\";\n\n        public static string RequestHeaderValueSeparatorColor { get; } = \"colors.request.header.valueSeparator\";\n\n        public static string RequestHeaderValueColor { get; } = \"colors.request.header.value\";\n\n        public static string RequestHeaderColor { get; } = \"colors.request.header\";\n\n        public static string RequestProtocolColor { get; } = \"colors.request.protocol\";\n\n        public static string RequestProtocolNameColor { get; } = \"colors.request.protocol.name\";\n\n        public static string RequestProtocolSeparatorColor { get; } = \"colors.request.protocol.separator\";\n\n        public static string RequestProtocolVersionColor { get; } = \"colors.request.protocol.version\";\n\n        public static string RequestStatusColor { get; } = \"colors.request.status\";\n\n        public static string RequestStatusCodeColor { get; } = \"colors.request.status.code\";\n\n        public static string RequestStatusReaseonPhraseColor { get; } = \"colors.request.status.reasonPhrase\";\n\n        public static string RequestMethodColor { get; } = \"colors.request.method\";\n\n        public static string RequestAddressColor { get; } = \"colors.request.address\";\n\n\n        public static string ResponseColor { get; } = \"colors.response\";\n\n        public static string ResponseBodyColor { get; } = \"colors.response.body\";\n\n        public static string ResponseSchemeColor { get; } = \"colors.response.scheme\";\n\n        public static string ResponseHeaderKeyColor { get; } = \"colors.response.header.key\";\n\n        public static string ResponseHeaderSeparatorColor { get; } = \"colors.response.header.separator\";\n\n        public static string ResponseHeaderValueSeparatorColor { get; } = \"colors.response.header.valueSeparator\";\n\n        public static string ResponseHeaderValueColor { get; } = \"colors.response.header.value\";\n\n        public static string ResponseHeaderColor { get; } = \"colors.response.header\";\n\n        public static string ResponseProtocolColor { get; } = \"colors.response.protocol\";\n\n        public static string ResponseProtocolNameColor { get; } = \"colors.response.protocol.name\";\n\n        public static string ResponseProtocolSeparatorColor { get; } = \"colors.response.protocol.separator\";\n\n        public static string ResponseProtocolVersionColor { get; } = \"colors.response.protocol.version\";\n\n        public static string ResponseStatusColor { get; } = \"colors.response.status\";\n\n        public static string ResponseStatusCodeColor { get; } = \"colors.response.status.code\";\n\n        public static string ResponseStatusReaseonPhraseColor { get; } = \"colors.response.status.reasonPhrase\";\n\n        public static string RequestOrResponseColor { get; } = \"colors.requestOrResponse\";\n\n        public static string ErrorColor { get; } = \"colors.error\";\n\n        public static string WarningColor { get; } = \"colors.warning\";\n\n        public static string BodyColor { get; } = \"colors.body\";\n\n        public static string SchemeColor { get; } = \"colors.scheme\";\n\n        public static string HeaderKeyColor { get; } = \"colors.header.key\";\n\n        public static string HeaderSeparatorColor { get; } = \"colors.header.separator\";\n\n        public static string HeaderValueSeparatorColor { get; } = \"colors.header.valueSeparator\";\n\n        public static string HeaderValueColor { get; } = \"colors.header.value\";\n\n        public static string HeaderColor { get; } = \"colors.header\";\n\n        public static string ProtocolColor { get; } = \"colors.protocol\";\n\n        public static string ProtocolNameColor { get; } = \"colors.protocol.name\";\n\n        public static string ProtocolSeparatorColor { get; } = \"colors.protocol.separator\";\n\n        public static string ProtocolVersionColor { get; } = \"colors.protocol.version\";\n\n        public static string StatusColor { get; } = \"colors.status\";\n\n        public static string StatusCodeColor { get; } = \"colors.status.code\";\n\n        public static string StatusReaseonPhraseColor { get; } = \"colors.status.reasonPhrase\";\n\n\n        public static string DefaultEditorCommand { get; } = \"editor.command.default\";\n\n        public static string DefaultEditorArguments { get; } = \"editor.command.default.arguments\";\n\n        public static string SwaggerRequeryBehavior { get; } = \"swagger.requery\";\n\n\n        public static AllowedColors GetColorPreference(this HttpState programState, string preference, AllowedColors defaultvalue = AllowedColors.None)\n        {\n            if (!programState.Preferences.TryGetValue(preference, out string preferenceValueString) || !Enum.TryParse(preferenceValueString, true, out AllowedColors result))\n            {\n                result = defaultvalue;\n            }\n\n            return result;\n        }\n\n        public static int GetIntPreference(this HttpState programState, string preference, int defaultValue = 0)\n        {\n            if (!programState.Preferences.TryGetValue(preference, out string preferenceValueString) || !int.TryParse(preferenceValueString, out int result))\n            {\n                result = defaultValue;\n            }\n\n            return result;\n        }\n\n        public static string GetStringPreference(this HttpState programState, string preference, string defaultValue = null)\n        {\n            if (!programState.Preferences.TryGetValue(preference, out string result))\n            {\n                result = defaultValue;\n            }\n\n            return result;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Program.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Repl;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\nusing Microsoft.HttpRepl.Commands;\n\nnamespace Microsoft.HttpRepl\n{\n    class Program\n    {\n        static async Task Main(string[] args)\n        {\n            var state = new HttpState();\n\n            if (Console.IsOutputRedirected)\n            {\n                Reporter.Error.WriteLine(\"Cannot start the REPL when output is being redirected\".SetColor(state.ErrorColor));\n                return;\n            }\n\n            var dispatcher = DefaultCommandDispatcher.Create(state.GetPrompt, state);\n            dispatcher.AddCommand(new ChangeDirectoryCommand());\n            dispatcher.AddCommand(new ClearCommand());\n            //dispatcher.AddCommand(new ConfigCommand());\n            dispatcher.AddCommand(new DeleteCommand());\n            dispatcher.AddCommand(new EchoCommand());\n            dispatcher.AddCommand(new ExitCommand());\n            dispatcher.AddCommand(new HeadCommand());\n            dispatcher.AddCommand(new HelpCommand());\n            dispatcher.AddCommand(new GetCommand());\n            dispatcher.AddCommand(new ListCommand());\n            dispatcher.AddCommand(new OptionsCommand());\n            dispatcher.AddCommand(new PatchCommand());\n            dispatcher.AddCommand(new PrefCommand());\n            dispatcher.AddCommand(new PostCommand());\n            dispatcher.AddCommand(new PutCommand());\n            dispatcher.AddCommand(new RunCommand());\n            dispatcher.AddCommand(new SetBaseCommand());\n            dispatcher.AddCommand(new SetDiagCommand());\n            dispatcher.AddCommand(new SetHeaderCommand());\n            dispatcher.AddCommand(new SetSwaggerCommand());\n            dispatcher.AddCommand(new UICommand());\n\n            CancellationTokenSource source = new CancellationTokenSource();\n            var shell = new Shell(dispatcher);\n            shell.ShellState.ConsoleManager.AddBreakHandler(() => source.Cancel());\n            if (args.Length > 0)\n            {\n                if (string.Equals(args[0], \"--help\", StringComparison.OrdinalIgnoreCase) || string.Equals(args[0], \"-h\", StringComparison.OrdinalIgnoreCase))\n                {\n                    shell.ShellState.ConsoleManager.WriteLine(\"Usage: dotnet httprepl [<BASE_ADDRESS>] [options]\");\n                    shell.ShellState.ConsoleManager.WriteLine();\n                    shell.ShellState.ConsoleManager.WriteLine(\"Arguments:\");\n                    shell.ShellState.ConsoleManager.WriteLine(\"  <BASE_ADDRESS> - The initial base address for the REPL.\");\n                    shell.ShellState.ConsoleManager.WriteLine();\n                    shell.ShellState.ConsoleManager.WriteLine(\"Options:\");\n                    shell.ShellState.ConsoleManager.WriteLine(\"  --help - Show help information.\");\n\n                    shell.ShellState.ConsoleManager.WriteLine();\n                    shell.ShellState.ConsoleManager.WriteLine(\"REPL Commands:\");\n                    new HelpCommand().CoreGetHelp(shell.ShellState, (ICommandDispatcher<HttpState, ICoreParseResult>)shell.ShellState.CommandDispatcher, state);\n                    return;\n                }\n\n                shell.ShellState.CommandDispatcher.OnReady(shell.ShellState);\n                shell.ShellState.InputManager.SetInput(shell.ShellState, $\"set base \\\"{args[0]}\\\"\");\n                await shell.ShellState.CommandDispatcher.ExecuteCommandAsync(shell.ShellState, CancellationToken.None).ConfigureAwait(false);\n            }\n            Task result = shell.RunAsync(source.Token);\n            await result.ConfigureAwait(false);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Properties/launchSettings.json",
    "content": "{\r\n  \"profiles\": {\r\n    \"Microsoft.HttpRepl\": {\r\n      \"commandName\": \"Project\",\r\n      \"commandLineArgs\": \"http://localhost\"\r\n    }\r\n  }\r\n}"
  },
  {
    "path": "src/Microsoft.HttpRepl/Suggestions/HeaderCompletion.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Microsoft.HttpRepl.Suggestions\n{\n    public class HeaderCompletion\n    {\n        private static readonly IEnumerable<string> CommonHeaders = new[]\n       {\n            \"A-IM\",\n            \"Accept\",\n            \"Accept-Charset\",\n            \"Accept-Encoding\",\n            \"Accept-Language\",\n            \"Accept-Datetime\",\n            \"Access-Control-Request-Method\",\n            \"Access-Control-Request-Headers\",\n            \"Authorization\",\n            \"Cache-Control\",\n            \"Connection\",\n            \"Content-Length\",\n            \"Content-MD5\",\n            \"Content-Type\",\n            \"Cookie\",\n            \"Date\",\n            \"Expect\",\n            \"Forwarded\",\n            \"From\",\n            \"Host\",\n            \"If-Match\",\n            \"If-Modified-Since\",\n            \"If-None-Match\",\n            \"If-Range\",\n            \"If-Unmodified-Since\",\n            \"Max-Forwards\",\n            \"Origin\",\n            \"Pragma\",\n            \"Proxy-Authentication\",\n            \"Range\",\n            \"Referer\",\n            \"TE\",\n            \"User-Agent\",\n            \"Upgrade\",\n            \"Via\",\n            \"Warning\",\n            //Non-standard\n            \"Upgrade-Insecure-Requests\",\n            \"X-Requested-With\",\n            \"DNT\",\n            \"X-Forwarded-For\",\n            \"X-Forwarded-Host\",\n            \"X-Forwarded-Proto\",\n            \"Front-End-Https\",\n            \"X-Http-Method-Override\",\n            \"X-ATT-DeviceId\",\n            \"X-Wap-Profile\",\n            \"Proxy-Connection\",\n            \"X-UIDH\",\n            \"X-Csrf-Token\",\n            \"X-Request-ID\",\n            \"X-Correlation-ID\"\n        };\n\n        private static readonly IReadOnlyList<string> DefaultContentTypesList = null;\n\n        public static IEnumerable<string> GetCompletions(IReadOnlyCollection<string> existingHeaders, string prefix)\n        {\n            List<string> result = CommonHeaders.Where(x => x.StartsWith(prefix, StringComparison.OrdinalIgnoreCase) && !(existingHeaders?.Contains(x) ?? false)).ToList();\n\n            if (result.Count > 0)\n            {\n                return result;\n            }\n\n            return null;\n        }\n\n        public static IEnumerable<string> GetValueCompletions(string method, string path, string header, string prefix, HttpState programState)\n        {\n            switch (header.ToUpperInvariant())\n            {\n                case \"CONTENT-TYPE\":\n                    IEnumerable<string> results = programState.GetApplicableContentTypes(method, path) ?? DefaultContentTypesList;\n\n                    if (results is null)\n                    {\n                        return null;\n                    }\n\n                    return results.Where(x => !string.IsNullOrEmpty(x) && x.StartsWith(prefix, StringComparison.OrdinalIgnoreCase));\n                default:\n                    return null;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.HttpRepl/Suggestions/ServerPathCompletion.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Microsoft.HttpRepl.Suggestions\n{\n    public static class ServerPathCompletion\n    {\n        public static IEnumerable<string> GetCompletions(HttpState programState, string normalCompletionString)\n        {\n\n            //If it's an absolute URI, nothing to suggest\n            if (Uri.TryCreate(normalCompletionString, UriKind.Absolute, out Uri _))\n            {\n                return null;\n            }\n\n            string path = normalCompletionString.Replace('\\\\', '/');\n            int searchFrom = normalCompletionString.Length - 1;\n            int lastSlash = path.LastIndexOf('/', searchFrom);\n            string prefix;\n\n            if (lastSlash < 0)\n            {\n                path = string.Empty;\n                prefix = normalCompletionString;\n            }\n            else\n            {\n                path = path.Substring(0, lastSlash + 1);\n                prefix = normalCompletionString.Substring(lastSlash + 1);\n            }\n\n            IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse()).TraverseTo(path);\n\n            if (s?.DirectoryNames == null)\n            {\n                return null;\n            }\n\n            List<string> results = new List<string>();\n\n            foreach (string child in s.DirectoryNames)\n            {\n                if (child.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))\n                {\n                    results.Add(path + child);\n                }\n            }\n\n            return results;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Commanding/CommandHistory.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace Microsoft.Repl.Commanding\n{\n    public class CommandHistory : ICommandHistory\n    {\n        private readonly int _maxEntries;\n        private readonly List<string> _commandLines = new List<string>();\n        private int _currentCommand = -1;\n        private int _suspensionDepth;\n\n        public CommandHistory(int maxEntries = 50)\n        {\n            _maxEntries = maxEntries;\n        }\n\n        public void AddCommand(string command)\n        {\n            if (_suspensionDepth > 0)\n            {\n                return;\n            }\n\n            _commandLines.Add(command);\n            if (_commandLines.Count > _maxEntries)\n            {\n                _commandLines.RemoveAt(0);\n            }\n            _currentCommand = -1;\n        }\n\n        public string GetNextCommand()\n        {\n            if (_commandLines.Count == 0)\n            {\n                return string.Empty;\n            }\n\n            if (_currentCommand == -1 || _currentCommand >= _commandLines.Count - 1)\n            {\n                _currentCommand = -1;\n                return string.Empty;\n            }\n\n            return _commandLines[++_currentCommand];\n        }\n\n        public string GetPreviousCommand()\n        {\n            if (_commandLines.Count == 0)\n            {\n                return string.Empty;\n            }\n\n            if (_currentCommand == -1)\n            {\n                _currentCommand = _commandLines.Count;\n            }\n\n            if (_currentCommand > 0)\n            {\n                return _commandLines[--_currentCommand];\n            }\n\n            return _commandLines[0];\n        }\n\n        public IDisposable SuspendHistory()\n        {\n            ++_suspensionDepth;\n            return new Disposable(() => --_suspensionDepth);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Commanding/CommandInputLocation.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.Repl.Commanding\n{\n    public enum CommandInputLocation\n    {\n        CommandName,\n        Argument,\n        OptionName,\n        OptionValue\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Commanding/CommandInputProcessingIssue.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.Repl.Commanding\n{\n    public class CommandInputProcessingIssue\n    {\n        public CommandInputProcessingIssueKind Kind { get; }\n\n        public string Text { get; }\n\n        public CommandInputProcessingIssue(CommandInputProcessingIssueKind kind, string text)\n        {\n            Kind = kind;\n            Text = text;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Commanding/CommandInputProcessingIssueKind.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.Repl.Commanding\n{\n    public enum CommandInputProcessingIssueKind\n    {\n        CommandMismatch,\n        ArgumentCountOutOfRange,\n        UnknownOption,\n        OptionUseCountOutOfRange,\n        MissingRequiredOptionInput,\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Commanding/CommandInputSpecification.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.Repl.Commanding\n{\n    public class CommandInputSpecification\n    {\n        public IReadOnlyList<IReadOnlyList<string>> CommandName { get; }\n\n        public char OptionPreamble { get; }\n\n        public int MinimumArguments { get; }\n\n        public int MaximumArguments { get; }\n\n        public IReadOnlyList<CommandOptionSpecification> Options { get; }\n\n        public CommandInputSpecification(IReadOnlyList<IReadOnlyList<string>> name, char optionPreamble, IReadOnlyList<CommandOptionSpecification> options, int minimumArgs, int maximumArgs)\n        {\n            CommandName = name;\n            OptionPreamble = optionPreamble;\n            MinimumArguments = minimumArgs;\n            MaximumArguments = maximumArgs;\n\n            if (MinimumArguments < 0)\n            {\n                MinimumArguments = 0;\n            }\n\n            if (MaximumArguments < MinimumArguments)\n            {\n                MaximumArguments = MinimumArguments;\n            }\n\n            Options = options;\n        }\n\n        public static CommandInputSpecificationBuilder Create(string baseName, params string[] additionalNameParts)\n        {\n            List<string> nameParts = new List<string> {baseName};\n            nameParts.AddRange(additionalNameParts);\n            return new CommandInputSpecificationBuilder(nameParts);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Commanding/CommandInputSpecificationBuilder.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace Microsoft.Repl.Commanding\n{\n    public class CommandInputSpecificationBuilder\n    {\n        private readonly List<IReadOnlyList<string>> _name;\n        private char _optionPreamble;\n        private int _minimumArgs;\n        private int _maximumArgs;\n        private readonly List<CommandOptionSpecification> _options = new List<CommandOptionSpecification>();\n\n        public CommandInputSpecificationBuilder(IReadOnlyList<string> name)\n        {\n            _name = new List<IReadOnlyList<string>> { name };\n            _optionPreamble = '-';\n        }\n\n        public CommandInputSpecificationBuilder WithOptionPreamble(char optionChar)\n        {\n            _optionPreamble = optionChar;\n            return this;\n        }\n\n        public CommandInputSpecificationBuilder ExactArgCount(int count)\n        {\n            _minimumArgs = count;\n            _maximumArgs = count;\n            return this;\n        }\n\n        public CommandInputSpecificationBuilder MinimumArgCount(int count)\n        {\n            _minimumArgs = count;\n            if (_maximumArgs < count)\n            {\n                _maximumArgs = count;\n            }\n\n            return this;\n        }\n\n        public CommandInputSpecificationBuilder MaximumArgCount(int count)\n        {\n            _maximumArgs = count;\n\n            if (_minimumArgs > count)\n            {\n                _minimumArgs = count;\n            }\n\n            return this;\n        }\n\n        public CommandInputSpecificationBuilder WithOption(CommandOptionSpecification option)\n        {\n            _options.Add(option);\n            return this;\n        }\n\n        public CommandInputSpecification Finish()\n        {\n            return new CommandInputSpecification(_name, _optionPreamble, _options, _minimumArgs, _maximumArgs);\n        }\n\n        public CommandInputSpecificationBuilder AlternateName(string baseName, params string[] additionalNameParts)\n        {\n            List<string> nameParts = new List<string> { baseName };\n            nameParts.AddRange(additionalNameParts);\n            _name.Add(nameParts);\n            return this;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Commanding/CommandOptionSpecification.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.Repl.Commanding\n{\n    public class CommandOptionSpecification\n    {\n        public string Id { get; }\n\n        public IReadOnlyList<string> Forms { get; }\n\n        public int MaximumOccurrences { get; }\n\n        public int MinimumOccurrences { get; }\n\n        public bool AcceptsValue { get; }\n\n        public bool RequiresValue { get; }\n\n        public CommandOptionSpecification(string id, bool acceptsValue = false, bool requiresValue = false, int minimumOccurrences = 0, int maximumOccurrences = int.MaxValue, params string[] forms)\n        {\n            Id = id;\n            Forms = forms;\n            MinimumOccurrences = minimumOccurrences;\n            MaximumOccurrences = maximumOccurrences > minimumOccurrences ? maximumOccurrences : minimumOccurrences;\n            RequiresValue = requiresValue;\n            AcceptsValue = RequiresValue || acceptsValue;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.Repl.Commanding\n{\n    public abstract class CommandWithStructuredInputBase<TProgramState, TParseResult> : ICommand<TProgramState, TParseResult>\n        where TParseResult : ICoreParseResult\n    {\n        public abstract string GetHelpSummary(IShellState shellState, TProgramState programState);\n\n        public string GetHelpDetails(IShellState shellState, TProgramState programState, TParseResult parseResult)\n        {\n            if (!DefaultCommandInput<TParseResult>.TryProcess(InputSpec, parseResult, out DefaultCommandInput<TParseResult> commandInput, out IReadOnlyList<CommandInputProcessingIssue> processingIssues) \n                && processingIssues.Any(x => x.Kind == CommandInputProcessingIssueKind.CommandMismatch))\n            {\n                //If this is the right command, just not the right syntax, report the usage errors\n                return null;\n            }\n\n            return GetHelpDetails(shellState, programState, commandInput, parseResult);\n        }\n\n        protected abstract string GetHelpDetails(IShellState shellState, TProgramState programState, DefaultCommandInput<TParseResult> commandInput, TParseResult parseResult);\n\n        public IEnumerable<string> Suggest(IShellState shellState, TProgramState programState, TParseResult parseResult)\n        {\n            DefaultCommandInput<TParseResult>.TryProcess(InputSpec, parseResult, out DefaultCommandInput<TParseResult> commandInput, out IReadOnlyList<CommandInputProcessingIssue> _);\n\n            string normalCompletionString = parseResult.SelectedSection == parseResult.Sections.Count\n                ? string.Empty\n                : parseResult.Sections[parseResult.SelectedSection].Substring(0, parseResult.CaretPositionWithinSelectedSection);\n\n            //If we're completing in a name position, offer completion for the command name\n            if (parseResult.SelectedSection < InputSpec.CommandName.Count)\n            {\n                IReadOnlyList<string> commandName = null;\n                for (int j = 0; j < InputSpec.CommandName.Count; ++j)\n                {\n                    bool success = true;\n                    for (int i = 0; i < parseResult.SelectedSection; ++i)\n                    {\n                        if (!string.Equals(InputSpec.CommandName[j][i], parseResult.Sections[i], StringComparison.OrdinalIgnoreCase))\n                        {\n                            success = false;\n                            break;\n                        }\n                    }\n\n                    if (success)\n                    {\n                        commandName = InputSpec.CommandName[j];\n                        break;\n                    }\n                }\n\n                if (commandName is null)\n                {\n                    return null;\n                }\n\n                if (commandName[parseResult.SelectedSection].StartsWith(normalCompletionString, StringComparison.OrdinalIgnoreCase))\n                {\n                    return new[] {commandName[parseResult.SelectedSection]};\n                }\n            }\n\n            if (commandInput is null)\n            {\n                return null;\n            }\n\n            if (normalCompletionString.StartsWith(InputSpec.OptionPreamble))\n            {\n                return GetOptionCompletions(commandInput, normalCompletionString);\n            }\n\n            IEnumerable<string> completions = Enumerable.Empty<string>();\n            CommandInputLocation? inputLocation = commandInput.SelectedElement?.Location;\n\n            if (inputLocation != CommandInputLocation.OptionValue && commandInput.Arguments.Count < InputSpec.MaximumArguments)\n            {\n                IEnumerable<string> results = GetArgumentSuggestionsForText(shellState, programState, parseResult, commandInput, normalCompletionString);\n\n                if (results != null)\n                {\n                    completions = results;\n                }\n            }\n\n            switch (inputLocation)\n            {\n                case CommandInputLocation.OptionName:\n                {\n                    IEnumerable<string> results = GetOptionCompletions(commandInput, normalCompletionString);\n\n                    if (results != null)\n                    {\n                        completions = completions.Union(results);\n                    }\n\n                    break;\n                }\n                case CommandInputLocation.OptionValue:\n                {\n                    IEnumerable<string> results = GetOptionValueCompletions(shellState, programState, commandInput.SelectedElement.Owner.NormalizedText, commandInput, parseResult, normalCompletionString);\n\n                    if (results != null)\n                    {\n                        completions = completions.Union(results);\n                    }\n\n                    break;\n                }\n                case CommandInputLocation.Argument:\n                {\n                    IEnumerable<string> argumentResults = GetArgumentSuggestionsForText(shellState, programState, parseResult, commandInput, normalCompletionString);\n\n                    if (argumentResults != null)\n                    {\n                        completions = completions.Union(argumentResults);\n                    }\n\n                    if (string.IsNullOrEmpty(normalCompletionString))\n                    {\n                        IEnumerable<string> results = GetOptionCompletions(commandInput, normalCompletionString);\n\n                        if (results != null)\n                        {\n                            completions = completions.Union(results);\n                        }\n                    }\n\n                    break;\n                }\n            }\n\n            return completions;\n        }\n\n        protected virtual IEnumerable<string> GetOptionValueCompletions(IShellState shellState, TProgramState programState, string optionId, DefaultCommandInput<TParseResult> commandInput, TParseResult parseResult, string normalizedCompletionText)\n        {\n            return null;\n        }\n\n        protected virtual IEnumerable<string> GetArgumentSuggestionsForText(IShellState shellState, TProgramState programState, TParseResult parseResult, DefaultCommandInput<TParseResult> commandInput, string normalCompletionString)\n        {\n            return null;\n        }\n\n        private IEnumerable<string> GetOptionCompletions(DefaultCommandInput<TParseResult> commandInput, string normalCompletionString)\n        {\n            return InputSpec.Options.Where(x => commandInput.Options[x.Id].Count < x.MaximumOccurrences)\n                .SelectMany(x => x.Forms)\n                .Where(x => x.StartsWith(normalCompletionString, StringComparison.OrdinalIgnoreCase));\n        }\n\n        public bool? CanHandle(IShellState shellState, TProgramState programState, TParseResult parseResult)\n        {\n            if (!DefaultCommandInput<TParseResult>.TryProcess(InputSpec, parseResult, out DefaultCommandInput<TParseResult> commandInput, out IReadOnlyList<CommandInputProcessingIssue> processingIssues))\n            {\n                //If this is the right command, just not the right syntax, report the usage errors\n                if (processingIssues.All(x => x.Kind != CommandInputProcessingIssueKind.CommandMismatch))\n                {\n                    foreach (CommandInputProcessingIssue issue in processingIssues)\n                    {\n                        shellState.ConsoleManager.Error.WriteLine(GetStringForIssue(issue));\n                    }\n\n                    string help = GetHelpDetails(shellState, programState, parseResult);\n                    shellState.ConsoleManager.WriteLine(help);\n                    return false;\n                }\n\n                //If there was a mismatch in the command name, this isn't our input to handle\n                return null;\n            }\n\n            return CanHandle(shellState, programState, commandInput);\n        }\n\n        protected virtual bool CanHandle(IShellState shellState, TProgramState programState, DefaultCommandInput<TParseResult> commandInput)\n        {\n            return true;\n        }\n\n        protected virtual string GetStringForIssue(CommandInputProcessingIssue issue)\n        {\n            //TODO: Make this nicer\n            return issue.Kind + \" -- \" + issue.Text;\n        }\n\n        public Task ExecuteAsync(IShellState shellState, TProgramState programState, TParseResult parseResult, CancellationToken cancellationToken)\n        {\n            if (!DefaultCommandInput<TParseResult>.TryProcess(InputSpec, parseResult, out DefaultCommandInput<TParseResult> commandInput, out IReadOnlyList<CommandInputProcessingIssue> _))\n            {\n                return Task.CompletedTask;\n            }\n\n            return ExecuteAsync(shellState, programState, commandInput, parseResult, cancellationToken);\n        }\n\n        protected abstract Task ExecuteAsync(IShellState shellState, TProgramState programState, DefaultCommandInput<TParseResult> commandInput, TParseResult parseResult, CancellationToken cancellationToken);\n\n        public abstract CommandInputSpecification InputSpec { get; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.Repl.Commanding\n{\n    public static class DefaultCommandDispatcher\n    {\n        public static DefaultCommandDispatcher<TProgramState> Create<TProgramState>(Func<string> getPrompt, TProgramState programState)\n        {\n            return new DefaultCommandDispatcher<TProgramState>(getPrompt, programState);\n        }\n\n        public static DefaultCommandDispatcher<TProgramState> Create<TProgramState>(Action<IShellState> onReady, TProgramState programState)\n        {\n            return new DefaultCommandDispatcher<TProgramState>(onReady, programState);\n        }\n\n        public static DefaultCommandDispatcher<TProgramState, TParseResult> Create<TProgramState, TParseResult>(Func<string> getPrompt, TProgramState programState, IParser<TParseResult> parser)\n            where TParseResult : ICoreParseResult\n        {\n            return new DefaultCommandDispatcher<TProgramState, TParseResult>(getPrompt, programState, parser);\n        }\n\n        public static DefaultCommandDispatcher<TProgramState, TParseResult> Create<TProgramState, TParseResult>(Action<IShellState> onReady, TProgramState programState, IParser<TParseResult> parser)\n            where TParseResult : ICoreParseResult\n        {\n            return new DefaultCommandDispatcher<TProgramState, TParseResult>(onReady, programState, parser);\n        }\n    }\n\n    public class DefaultCommandDispatcher<TProgramState> : DefaultCommandDispatcher<TProgramState, ICoreParseResult>\n    {\n        public DefaultCommandDispatcher(Func<string> getPrompt, TProgramState programState)\n            : base(getPrompt, programState, new CoreParser())\n        {\n        }\n\n        public DefaultCommandDispatcher(Action<IShellState> onReady, TProgramState programState)\n            : base(onReady, programState, new CoreParser())\n        {\n        }\n    }\n\n    public class DefaultCommandDispatcher<TProgramState, TParseResult> : ICommandDispatcher<TProgramState, TParseResult>\n        where TParseResult : ICoreParseResult\n    {\n        private readonly Action<IShellState> _onReady;\n        private readonly TProgramState _programState;\n        private readonly IParser<TParseResult> _parser;\n        private readonly HashSet<ICommand<TProgramState, TParseResult>> _commands = new HashSet<ICommand<TProgramState, TParseResult>>();\n        private bool _isReady;\n\n        public DefaultCommandDispatcher(Func<string> getPrompt, TProgramState programState, IParser<TParseResult> parser)\n            : this(s => s.ConsoleManager.Write(getPrompt()), programState, parser)\n        {\n        }\n\n        public DefaultCommandDispatcher(Action<IShellState> onReady, TProgramState programState, IParser<TParseResult> parser)\n        {\n            _onReady = onReady;\n            _programState = programState;\n            _parser = parser;\n        }\n\n        public void AddCommand(ICommand<TProgramState, TParseResult> command)\n        {\n            _commands.Add(command);\n        }\n\n        public IEnumerable<ICommand<TProgramState, TParseResult>> Commands => _commands;\n\n        public IParser Parser => _parser;\n\n        public IReadOnlyList<string> CollectSuggestions(IShellState shellState)\n        {\n            string line = shellState.InputManager.GetCurrentBuffer();\n            TParseResult parseResult = _parser.Parse(line, shellState.ConsoleManager.CaretPosition);\n            HashSet<string> suggestions = new HashSet<string>(StringComparer.OrdinalIgnoreCase);\n\n            foreach (ICommand<TProgramState, TParseResult> command in _commands)\n            {\n                IEnumerable<string> commandSuggestions = command.Suggest(shellState, _programState, parseResult);\n\n                if (commandSuggestions != null)\n                {\n                    suggestions.UnionWith(commandSuggestions);\n                }\n            }\n\n            return suggestions.OrderBy(x => x, StringComparer.OrdinalIgnoreCase).ToList();\n        }\n\n        public async Task ExecuteCommandAsync(IShellState shellState, CancellationToken cancellationToken)\n        {\n            _isReady = false;\n            shellState.ConsoleManager.WriteLine();\n            string commandText = shellState.InputManager.GetCurrentBuffer();\n\n            if (!string.IsNullOrWhiteSpace(commandText))\n            {\n                shellState.CommandHistory.AddCommand(shellState.InputManager.GetCurrentBuffer());\n\n                try\n                {\n                    await ExecuteCommandInternalAsync(shellState, cancellationToken).ConfigureAwait(false);\n                }\n                catch (Exception ex)\n                {\n                    shellState.ConsoleManager.Error.WriteLine(ex.ToString().Bold().Red());\n                }\n\n                if (cancellationToken.IsCancellationRequested)\n                {\n                    shellState.ConsoleManager.Error.WriteLine(\"Execution was cancelled\".Bold().Red());\n                }\n            }\n\n            if (!_isReady)\n            {\n                shellState.ConsoleManager.WriteLine();\n                OnReady(shellState);\n            }\n\n            shellState.InputManager.ResetInput();\n        }\n\n        private async Task ExecuteCommandInternalAsync(IShellState shellState, CancellationToken cancellationToken)\n        {\n            string line = shellState.InputManager.GetCurrentBuffer();\n            TParseResult parseResult = _parser.Parse(line, shellState.ConsoleManager.CaretPosition);\n\n            if (!string.IsNullOrWhiteSpace(parseResult.CommandText))\n            {\n                foreach (ICommand<TProgramState, TParseResult> command in _commands)\n                {\n                    bool? result = command.CanHandle(shellState, _programState, parseResult);\n\n                    if (result.HasValue)\n                    {\n                        if (result.Value)\n                        {\n                            await command.ExecuteAsync(shellState, _programState, parseResult, cancellationToken);\n                        }\n\n                        //If the handler returned non-null, the input would be directed to it, but it's not valid input\n                        return;\n                    }\n                }\n\n                shellState.ConsoleManager.Error.WriteLine(\"No matching command found\".Red().Bold());\n                shellState.ConsoleManager.Error.WriteLine(\"Execute 'help' to see available commands\".Red().Bold());\n            }\n        }\n\n        public void OnReady(IShellState shellState)\n        {\n            if (!_isReady)\n            {\n                _onReady(shellState);\n                shellState.ConsoleManager.ResetCommandStart();\n                _isReady = true;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Commanding/DefaultCommandInput.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.Repl.Commanding\n{\n    public class DefaultCommandInput<TParseResult>\n        where TParseResult : ICoreParseResult\n    {\n        public DefaultCommandInput(IReadOnlyList<InputElement> commandName, IReadOnlyList<InputElement> arguments, IReadOnlyDictionary<string, IReadOnlyList<InputElement>> options, InputElement selectedElement)\n        {\n            CommandName = commandName;\n            Arguments = arguments;\n            Options = options;\n            SelectedElement = selectedElement;\n        }\n\n        public static bool TryProcess(CommandInputSpecification spec, TParseResult parseResult, out DefaultCommandInput<TParseResult> result, out IReadOnlyList<CommandInputProcessingIssue> processingIssues)\n        {\n            List<CommandInputProcessingIssue> issues = null;\n            List<InputElement> commandNameElements = null;\n\n            foreach (IReadOnlyList<string> commandName in spec.CommandName)\n            {\n                if (TryProcessCommandName(commandName, parseResult, out List<InputElement> nameElements, out issues))\n                {\n                    commandNameElements = nameElements;\n                    break;\n                }\n            }\n\n            if (commandNameElements is null)\n            {\n                result = null;\n                processingIssues = issues;\n                return false;\n            }\n\n            List<InputElement> arguments = new List<InputElement>();\n            Dictionary<InputElement, InputElement> options = new Dictionary<InputElement, InputElement>();\n            InputElement currentOption = null;\n            CommandOptionSpecification currentOptionSpec = null;\n            InputElement selectedElement = null;\n\n            for (int i = spec.CommandName.Count; i < parseResult.Sections.Count; ++i)\n            {\n                //If we're not looking at an option name\n                if (!parseResult.Sections[i].StartsWith(spec.OptionPreamble) || parseResult.IsQuotedSection(i))\n                {\n                    if (currentOption is null)\n                    {\n                        InputElement currentElement = new InputElement(CommandInputLocation.Argument, parseResult.Sections[i], parseResult.Sections[i], i);\n\n                        if (i == parseResult.SelectedSection)\n                        {\n                            selectedElement = currentElement;\n                        }\n\n                        arguments.Add(currentElement);\n                    }\n                    else\n                    {\n                        //If the option isn't a defined one or it is and indicates that it accepts a value, add the section as an option value,\n                        //  otherwise add it as an argument\n                        if (currentOptionSpec?.AcceptsValue ?? true)\n                        {\n                            InputElement currentElement = new InputElement(currentOption, CommandInputLocation.OptionValue, parseResult.Sections[i], parseResult.Sections[i], i);\n\n                            if (i == parseResult.SelectedSection)\n                            {\n                                selectedElement = currentElement;\n                            }\n\n                            options[currentOption] = currentElement;\n                            currentOption = null;\n                            currentOptionSpec = null;\n                        }\n                        else\n                        {\n                            InputElement currentElement = new InputElement(CommandInputLocation.Argument, parseResult.Sections[i], parseResult.Sections[i], i);\n\n                            if (i == parseResult.SelectedSection)\n                            {\n                                selectedElement = currentElement;\n                            }\n\n                            arguments.Add(currentElement);\n                        }\n                    }\n                }\n                //If we are looking at an option name\n                else\n                {\n                    //Otherwise, check to see whether the previous option had a required argument before committing it\n                    if (!(currentOption is null))\n                    {\n                        options[currentOption] = null;\n\n                        if (currentOptionSpec?.RequiresValue ?? false)\n                        {\n                            issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.MissingRequiredOptionInput, currentOption.Text));\n                        }\n                    }\n\n                    CommandOptionSpecification optionSpec = spec.Options.FirstOrDefault(x => x.Forms.Any(y => string.Equals(y, parseResult.Sections[i], StringComparison.Ordinal)));\n\n                    if (optionSpec is null)\n                    {\n                        issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.UnknownOption, parseResult.Sections[i]));\n                    }\n\n                    currentOption = new InputElement(CommandInputLocation.OptionName, parseResult.Sections[i], optionSpec?.Id, i);\n\n                    if (i == parseResult.SelectedSection)\n                    {\n                        selectedElement = currentOption;\n                    }\n\n                    currentOptionSpec = optionSpec;\n                }\n            }\n\n            //Clear any option in progress\n            if (!(currentOption is null))\n            {\n                options[currentOption] = null;\n\n                if (currentOptionSpec?.RequiresValue ?? false)\n                {\n                    issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.MissingRequiredOptionInput, currentOption.Text));\n                }\n            }\n\n            //Check to make sure our argument count is in range, if not add an issue\n            if (arguments.Count > spec.MaximumArguments || arguments.Count < spec.MinimumArguments)\n            {\n                issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.ArgumentCountOutOfRange, arguments.Count.ToString()));\n            }\n\n            //Build up the dictionary of options by normal form, then validate counts for every option in the spec\n            Dictionary<string, IReadOnlyList<InputElement>> optionsByNormalForm = new Dictionary<string, IReadOnlyList<InputElement>>(StringComparer.Ordinal);\n\n            foreach (KeyValuePair<InputElement, InputElement> entry in options)\n            {\n                if (entry.Key.NormalizedText is null)\n                {\n                    continue;\n                }\n\n                if (!optionsByNormalForm.TryGetValue(entry.Key.NormalizedText, out IReadOnlyList<InputElement> rawBucket))\n                {\n                    optionsByNormalForm[entry.Key.NormalizedText] = rawBucket = new List<InputElement>();\n                }\n\n                List<InputElement> bucket = (List<InputElement>) rawBucket;\n                bucket.Add(entry.Value);\n            }\n\n            foreach (CommandOptionSpecification optionSpec in spec.Options)\n            {\n                if (!optionsByNormalForm.TryGetValue(optionSpec.Id, out IReadOnlyList<InputElement> values))\n                {\n                    optionsByNormalForm[optionSpec.Id] = values = new List<InputElement>();\n                }\n\n                if (values.Count < optionSpec.MinimumOccurrences || values.Count > optionSpec.MaximumOccurrences)\n                {\n                    issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.OptionUseCountOutOfRange, values.Count.ToString()));\n                }\n            }\n\n            result = new DefaultCommandInput<TParseResult>(commandNameElements, arguments, optionsByNormalForm, selectedElement);\n            processingIssues = issues;\n            return issues.Count == 0;\n        }\n\n        private static bool TryProcessCommandName(IReadOnlyList<string> commandName, TParseResult parseResult, out List<InputElement> nameElements, out List<CommandInputProcessingIssue> processingIssues)\n        {\n            List<CommandInputProcessingIssue> issues = new List<CommandInputProcessingIssue>();\n            List<InputElement> commandNameElements = new List<InputElement>();\n\n            if (commandName.Count > parseResult.Sections.Count)\n            {\n                issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.CommandMismatch, commandName[parseResult.Sections.Count]));\n            }\n\n            for (int i = 0; i < commandName.Count && i < parseResult.Sections.Count; ++i)\n            {\n                if (!string.Equals(commandName[i], parseResult.Sections[i], StringComparison.OrdinalIgnoreCase))\n                {\n                    issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.CommandMismatch, parseResult.Sections[i]));\n                }\n\n                commandNameElements.Add(new InputElement(CommandInputLocation.CommandName, parseResult.Sections[i], commandName[i], i));\n            }\n\n            processingIssues = issues;\n\n            //If we have a command name mismatch, no point in continuing\n            if (issues.Count > 0)\n            {\n                nameElements = null;\n                return false;\n            }\n\n            nameElements = commandNameElements;\n            return true;\n        }\n\n        public InputElement SelectedElement { get; }\n\n        public IReadOnlyList<InputElement> CommandName { get; }\n\n        public IReadOnlyList<InputElement> Arguments { get; }\n\n        public IReadOnlyDictionary<string, IReadOnlyList<InputElement>> Options { get; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Commanding/ICommand.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.Repl.Commanding\n{\n    public interface ICommand<in TProgramState, in TParseResult>\n        where TParseResult : ICoreParseResult\n    {\n        string GetHelpSummary(IShellState shellState, TProgramState programState);\n\n        string GetHelpDetails(IShellState shellState, TProgramState programState, TParseResult parseResult);\n\n        IEnumerable<string> Suggest(IShellState shellState, TProgramState programState, TParseResult parseResult);\n\n        bool? CanHandle(IShellState shellState, TProgramState programState, TParseResult parseResult);\n\n        Task ExecuteAsync(IShellState shellState, TProgramState programState, TParseResult parseResult, CancellationToken cancellationToken);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Commanding/ICommandDispatcher.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.Repl.Commanding\n{\n    public interface ICommandDispatcher\n    {\n        IParser Parser { get; }\n\n        IReadOnlyList<string> CollectSuggestions(IShellState shellState);\n\n        void OnReady(IShellState shellState);\n\n        Task ExecuteCommandAsync(IShellState shellState, CancellationToken cancellationToken);\n    }\n\n    public interface ICommandDispatcher<in TProgramState, in TParseResult> : ICommandDispatcher\n        where TParseResult : ICoreParseResult\n    {\n        IEnumerable<ICommand<TProgramState, TParseResult>> Commands { get; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Commanding/ICommandHistory.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\n\nnamespace Microsoft.Repl.Commanding\n{\n    public interface ICommandHistory\n    {\n        string GetPreviousCommand();\n\n        string GetNextCommand();\n\n        void AddCommand(string command);\n\n        IDisposable SuspendHistory();\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Commanding/InputElement.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.Repl.Commanding\n{\n    public class InputElement\n    {\n        public CommandInputLocation Location { get; }\n\n        public string Text { get; }\n\n        public string NormalizedText { get; }\n\n        public InputElement Owner { get; }\n\n        public int ParseResultSectionIndex { get; }\n\n        public InputElement(CommandInputLocation location, string text, string normalizedText, int sectionIndex)\n            : this(null, location, text, normalizedText, sectionIndex)\n        {\n        }\n\n        public InputElement(InputElement owner, CommandInputLocation location, string text, string normalizedText, int sectionIndex)\n        {\n            Owner = owner;\n            Location = location;\n            Text = text;\n            NormalizedText = normalizedText;\n            ParseResultSectionIndex = sectionIndex;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/ConsoleHandling/AllowedColors.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\n\nnamespace Microsoft.Repl.ConsoleHandling\n{\n    [Flags]\n    public enum AllowedColors\n    {\n        Black = 0x00,\n        BoldBlack = Bold | Black,\n        Red = 0x01,\n        BoldRed = Bold | Red,\n        Green = 0x02,\n        BoldGreen = Bold | Green,\n        Yellow = 0x03,\n        BoldYellow = Bold | Yellow,\n        Blue = 0x04,\n        BoldBlue = Bold | Blue,\n        Magenta = 0x05,\n        BoldMagenta = Bold | Magenta,\n        Cyan = 0x06,\n        BoldCyan = Bold | Cyan,\n        White = 0x07,\n        BoldWhite = White | Bold,\n        Bold = 0x100,\n        None = 0x99\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/ConsoleHandling/AnsiColorExtensions.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.Repl.ConsoleHandling\n{\n    public static class AnsiColorExtensions\n    {\n        public static string Black(this string text)\n        {\n            return \"\\x1B[30m\" + text + \"\\x1B[39m\";\n        }\n\n        public static string Red(this string text)\n        {\n            return \"\\x1B[31m\" + text + \"\\x1B[39m\";\n        }\n        public static string Green(this string text)\n        {\n            return \"\\x1B[32m\" + text + \"\\x1B[39m\";\n        }\n\n        public static string Yellow(this string text)\n        {\n            return \"\\x1B[33m\" + text + \"\\x1B[39m\";\n        }\n\n        public static string Blue(this string text)\n        {\n            return \"\\x1B[34m\" + text + \"\\x1B[39m\";\n        }\n\n        public static string Magenta(this string text)\n        {\n            return \"\\x1B[35m\" + text + \"\\x1B[39m\";\n        }\n\n        public static string Cyan(this string text)\n        {\n            return \"\\x1B[36m\" + text + \"\\x1B[39m\";\n        }\n\n        public static string White(this string text)\n        {\n            return \"\\x1B[37m\" + text + \"\\x1B[39m\";\n        }\n\n        public static string Bold(this string text)\n        {\n            return \"\\x1B[1m\" + text + \"\\x1B[22m\";\n        }\n\n        public static string SetColor(this string text, AllowedColors color)\n        {\n            if (color.HasFlag(AllowedColors.Bold))\n            {\n                text = text.Bold();\n                color = color & ~AllowedColors.Bold;\n            }\n\n            switch (color)\n            {\n                case AllowedColors.Black:\n                    return text.Black();\n                case AllowedColors.Red:\n                    return text.Red();\n                case AllowedColors.Green:\n                    return text.Green();\n                case AllowedColors.Yellow:\n                    return text.Yellow();\n                case AllowedColors.Blue:\n                    return text.Blue();\n                case AllowedColors.Magenta:\n                    return text.Magenta();\n                case AllowedColors.Cyan:\n                    return text.Cyan();\n                case AllowedColors.White:\n                    return text.White();\n                default:\n                    return text;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/ConsoleHandling/AnsiConsole.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\n\nnamespace Microsoft.Repl.ConsoleHandling\n{\n    public class AnsiConsole\n    {\n        private AnsiConsole(TextWriter writer)\n        {\n            Writer = writer;\n\n            OriginalForegroundColor = Console.ForegroundColor;\n        }\n\n        private int _boldRecursion;\n\n        public static AnsiConsole GetOutput()\n        {\n            return new AnsiConsole(Console.Out);\n        }\n\n        public static AnsiConsole GetError()\n        {\n            return new AnsiConsole(Console.Error);\n        }\n\n        public TextWriter Writer { get; }\n\n        public ConsoleColor OriginalForegroundColor { get; }\n\n        private void SetColor(ConsoleColor color)\n        {\n            const int light = 0x08;\n            int c = (int)color;\n\n            Console.ForegroundColor =\n                c < 0 ? color :                                   // unknown, just use it\n                _boldRecursion > 0 ? (ConsoleColor)(c | light) :  // ensure color is light\n                (ConsoleColor)(c & ~light);                       // ensure color is dark\n        }\n\n        private void SetBold(bool bold)\n        {\n            _boldRecursion += bold ? 1 : -1;\n            if (_boldRecursion > 1 || (_boldRecursion == 1 && !bold))\n            {\n                return;\n            }\n\n            // switches on _boldRecursion to handle boldness\n            SetColor(Console.ForegroundColor);\n        }\n\n        public void WriteLine(string message)\n        {\n            Write(message);\n            Writer.WriteLine();\n        }\n\n        public void Write(char message)\n        {\n            Writer.Write(message);\n        }\n\n        public void Write(string message)\n        {\n            if (message is null)\n            {\n                return;\n            }\n\n            var escapeScan = 0;\n            for (; ; )\n            {\n                var escapeIndex = message.IndexOf(\"\\x1b[\", escapeScan, StringComparison.Ordinal);\n                if (escapeIndex == -1)\n                {\n                    var text = message.Substring(escapeScan);\n                    Writer.Write(text);\n                    break;\n                }\n                else\n                {\n                    var startIndex = escapeIndex + 2;\n                    var endIndex = startIndex;\n                    while (endIndex != message.Length &&\n                        message[endIndex] >= 0x20 &&\n                        message[endIndex] <= 0x3f)\n                    {\n                        endIndex += 1;\n                    }\n\n                    var text = message.Substring(escapeScan, escapeIndex - escapeScan);\n                    Writer.Write(text);\n                    if (endIndex == message.Length)\n                    {\n                        break;\n                    }\n\n                    switch (message[endIndex])\n                    {\n                        case 'm':\n                            if (int.TryParse(message.Substring(startIndex, endIndex - startIndex), out int value))\n                            {\n                                switch (value)\n                                {\n                                    case 1:\n                                        SetBold(true);\n                                        break;\n                                    case 22:\n                                        SetBold(false);\n                                        break;\n                                    case 30:\n                                        SetColor(ConsoleColor.Black);\n                                        break;\n                                    case 31:\n                                        SetColor(ConsoleColor.Red);\n                                        break;\n                                    case 32:\n                                        SetColor(ConsoleColor.Green);\n                                        break;\n                                    case 33:\n                                        SetColor(ConsoleColor.Yellow);\n                                        break;\n                                    case 34:\n                                        SetColor(ConsoleColor.Blue);\n                                        break;\n                                    case 35:\n                                        SetColor(ConsoleColor.Magenta);\n                                        break;\n                                    case 36:\n                                        SetColor(ConsoleColor.Cyan);\n                                        break;\n                                    case 37:\n                                        SetColor(ConsoleColor.Gray);\n                                        break;\n                                    case 39:\n                                        Console.ForegroundColor = OriginalForegroundColor;\n                                        break;\n                                }\n                            }\n                            break;\n                    }\n\n                    escapeScan = endIndex + 1;\n                }\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/ConsoleHandling/ConsoleManager.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading;\n\nnamespace Microsoft.Repl.ConsoleHandling\n{\n    public class ConsoleManager : IConsoleManager\n    {\n        private readonly List<Action> _breakHandlers = new List<Action>();\n\n        public Point Caret => new Point(Console.CursorLeft, Console.CursorTop);\n\n        public Point CommandStart => new Point(Caret.X - CaretPosition % Console.BufferWidth, Caret.Y - CaretPosition / Console.BufferWidth);\n\n        public int CaretPosition { get; private set; }\n\n        public bool IsKeyAvailable => Console.KeyAvailable;\n\n        public bool IsCaretVisible\n        {\n            get => Reporter.Output.IsCaretVisible;\n            set => Reporter.Output.IsCaretVisible = value;\n        }\n\n        public ConsoleManager()\n        {\n            Error = new Writable(CaretUpdateScope, Reporter.Error);\n            Console.CancelKeyPress += OnCancelKeyPress;\n        }\n\n        public void Clear()\n        {\n            using (CaretUpdateScope())\n            {\n                Console.Clear();\n                ResetCommandStart();\n            }\n        }\n\n        public void MoveCaret(int positions)\n        {\n            using (CaretUpdateScope())\n            {\n                if (positions == 0)\n                {\n                    return;\n                }\n\n                int bufferWidth = Console.BufferWidth;\n                int cursorTop = Console.CursorTop;\n                int cursorLeft = Console.CursorLeft;\n\n                while (positions < 0 && CaretPosition > 0)\n                {\n                    if (-positions > bufferWidth)\n                    {\n                        if (cursorTop == 0)\n                        {\n                            cursorLeft = 0;\n                            positions = 0;\n                        }\n                        else\n                        {\n                            positions += bufferWidth;\n                            --cursorTop;\n                        }\n                    }\n                    else\n                    {\n                        int remaining = cursorLeft + positions;\n\n                        if (remaining >= 0)\n                        {\n                            cursorLeft = remaining;\n                        }\n                        else if (cursorTop == 0)\n                        {\n                            cursorLeft = 0;\n                        }\n                        else\n                        {\n                            --cursorTop;\n                            cursorLeft = bufferWidth + remaining;\n                        }\n\n                        positions = 0;\n                    }\n                }\n\n                while (positions > 0)\n                {\n                    if (positions > bufferWidth)\n                    {\n                        positions -= bufferWidth;\n                        ++cursorTop;\n                    }\n                    else\n                    {\n                        int spaceLeftOnLine = bufferWidth - cursorLeft - 1;\n                        if (positions > spaceLeftOnLine)\n                        {\n                            ++cursorTop;\n                            cursorLeft = positions - spaceLeftOnLine - 1;\n                        }\n                        else\n                        {\n                            cursorLeft += positions;\n                        }\n\n                        positions = 0;\n                    }\n                }\n\n                Console.SetCursorPosition(cursorLeft, cursorTop);\n            }\n        }\n\n        public ConsoleKeyInfo ReadKey(CancellationToken cancellationToken)\n        {\n            while (!Console.KeyAvailable && !cancellationToken.IsCancellationRequested)\n            {\n                Thread.Sleep(2);\n            }\n\n            if (cancellationToken.IsCancellationRequested)\n            {\n                return default(ConsoleKeyInfo);\n            }\n            else\n            {\n                return Console.ReadKey(true);\n            }\n        }\n\n        public void ResetCommandStart()\n        {\n            CaretPosition = 0;\n        }\n\n        public void Write(char c)\n        {\n            using (CaretUpdateScope())\n            {\n                Reporter.Output.Write(c);\n            }\n        }\n\n        public void Write(string s)\n        {\n            using (CaretUpdateScope())\n            {\n                Reporter.Output.Write(s);\n            }\n        }\n\n        public void WriteLine()\n        {\n            using (CaretUpdateScope())\n            {\n                Reporter.Output.WriteLine();\n            }\n        }\n\n        public void WriteLine(string s)\n        {\n            if (s is null)\n            {\n                return;\n            }\n\n            using (CaretUpdateScope())\n            {\n                Reporter.Output.WriteLine(s);\n            }\n        }\n\n        public IDisposable AddBreakHandler(Action handler)\n        {\n            Disposable result = new Disposable(() => ReleaseBreakHandler(handler));\n            _breakHandlers.Add(handler);\n            return result;\n        }\n\n        private IDisposable CaretUpdateScope()\n        {\n            Point currentCaret = Caret;\n            return new Disposable(() =>\n            {\n                int y = Caret.Y - currentCaret.Y;\n                int x = Caret.X - currentCaret.X;\n                CaretPosition += y * Console.BufferWidth + x;\n            });\n        }\n\n        private void OnCancelKeyPress(object sender, ConsoleCancelEventArgs e)\n        {\n            e.Cancel = true;\n            Action handler = _breakHandlers.LastOrDefault();\n            handler?.Invoke();\n        }\n\n        private void ReleaseBreakHandler(Action handler)\n        {\n            _breakHandlers.Remove(handler);\n        }\n\n        public IWritable Error { get; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/ConsoleHandling/IConsoleManager.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Threading;\n\nnamespace Microsoft.Repl.ConsoleHandling\n{\n    public interface IConsoleManager : IWritable\n    {\n        Point Caret { get; }\n\n        Point CommandStart { get; }\n\n        int CaretPosition { get; }\n\n        IWritable Error { get; }\n\n        bool IsKeyAvailable { get; }\n\n        void Clear();\n\n        void MoveCaret(int positions);\n\n        ConsoleKeyInfo ReadKey(CancellationToken cancellationToken);\n\n        void ResetCommandStart();\n\n        IDisposable AddBreakHandler(Action onBreak);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/ConsoleHandling/IWritable.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.Repl.ConsoleHandling\n{\n    public interface IWritable\n    {\n        void Write(char c);\n\n        void Write(string s);\n\n        void WriteLine();\n\n        void WriteLine(string s);\n\n        bool IsCaretVisible { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/ConsoleHandling/Point.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.Repl.ConsoleHandling\n{\n    public struct Point\n    {\n        public readonly int X;\n\n        public readonly int Y;\n\n        public Point(int x, int y)\n        {\n            X = x;\n            Y = y;\n        }\n\n        public static bool operator >(Point left, Point right)\n        {\n            return left.Y > right.Y || (left.Y == right.Y && right.X > left.X);\n        }\n\n        public static bool operator <(Point left, Point right)\n        {\n            return left.Y < right.Y || (left.Y == right.Y && right.X < left.X);\n        }\n\n        public static bool operator ==(Point left, Point right)\n        {\n            return left.X == right.X && left.Y == right.Y;\n        }\n\n        public static bool operator !=(Point left, Point right)\n        {\n            return left.X != right.X || left.Y != right.Y;\n        }\n\n        public override bool Equals(object obj)\n        {\n            return obj is Point other && other.X == X && other.Y == Y;\n        }\n\n        public override int GetHashCode()\n        {\n            return X ^ Y;\n        }\n\n        public override string ToString()\n        {\n            return $\"(X={X}, Y={Y})\";\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/ConsoleHandling/Reporter.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\n\nnamespace Microsoft.Repl.ConsoleHandling\n{\n    public class Reporter : IWritable\n    {\n        private static readonly Reporter NullReporter = new Reporter(null);\n        private static readonly object Sync = new object();\n\n        private readonly AnsiConsole _console;\n\n        static Reporter()\n        {\n            Reset();\n        }\n\n        private Reporter(AnsiConsole console)\n        {\n            _console = console;\n        }\n\n        public static Reporter Output { get; private set; }\n        public static Reporter Error { get; private set; }\n        public static Reporter Verbose { get; private set; }\n\n        /// <summary>\n        /// Resets the Reporters to write to the current Console Out/Error.\n        /// </summary>\n        public static void Reset()\n        {\n            lock (Sync)\n            {\n                Output = new Reporter(AnsiConsole.GetOutput());\n                Error = new Reporter(AnsiConsole.GetError());\n                Verbose = IsVerbose ?\n                    new Reporter(AnsiConsole.GetOutput()) :\n                    NullReporter;\n            }\n        }\n\n        public void WriteLine(string message)\n        {\n            if (message is null)\n            {\n                return;\n            }\n\n            lock (Sync)\n            {\n                if (ShouldPassAnsiCodesThrough)\n                {\n                    _console?.Writer?.WriteLine(message);\n                }\n                else\n                {\n                    _console?.WriteLine(message);\n                }\n            }\n        }\n\n        public void WriteLine()\n        {\n            lock (Sync)\n            {\n                _console?.Writer?.WriteLine();\n            }\n        }\n\n        public void Write(char message)\n        {\n            lock (Sync)\n            {\n                if (ShouldPassAnsiCodesThrough)\n                {\n                    _console?.Writer?.Write(message);\n                }\n                else\n                {\n                    _console?.Write(message);\n                }\n            }\n        }\n\n        public void Write(string message)\n        {\n            lock (Sync)\n            {\n                if (ShouldPassAnsiCodesThrough)\n                {\n                    _console?.Writer?.Write(message);\n                }\n                else\n                {\n                    _console?.Write(message);\n                }\n            }\n        }\n\n        private static bool IsVerbose => bool.TryParse(Environment.GetEnvironmentVariable(\"DOTNET_CLI_CONTEXT_VERBOSE\") ?? \"false\", out bool value) && value;\n\n        private bool ShouldPassAnsiCodesThrough => bool.TryParse(Environment.GetEnvironmentVariable(\"DOTNET_CLI_CONTEXT_ANSI_PASS_THRU\") ?? \"false\", out bool value) && value;\n\n        private bool _isCaretVisible = true;\n\n        public bool IsCaretVisible\n        {\n            get => _isCaretVisible;\n            set \n            {\n                Console.CursorVisible = value;\n                _isCaretVisible = value;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/ConsoleHandling/Writable.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\n\nnamespace Microsoft.Repl.ConsoleHandling\n{\n    internal class Writable : IWritable\n    {\n        private readonly Func<IDisposable> _caretUpdater;\n        private readonly Reporter _reporter;\n\n        public Writable(Func<IDisposable> caretUpdater, Reporter reporter)\n        {\n            _caretUpdater = caretUpdater;\n            _reporter = reporter;\n        }\n\n        public bool IsCaretVisible\n        {\n            get => _reporter.IsCaretVisible;\n            set => _reporter.IsCaretVisible = value;\n        }\n\n        public void Write(char c)\n        {\n            using (_caretUpdater())\n            {\n                _reporter.Write(c);\n            }\n        }\n\n        public void Write(string s)\n        {\n            using (_caretUpdater())\n            {\n                _reporter.Write(s);\n            }\n        }\n\n        public void WriteLine()\n        {\n            using (_caretUpdater())\n            {\n                _reporter.WriteLine();\n            }\n        }\n\n        public void WriteLine(string s)\n        {\n            using (_caretUpdater())\n            {\n                _reporter.WriteLine(s);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Disposable.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\n\nnamespace Microsoft.Repl\n{\n    public class Disposable : IDisposable\n    {\n        private Action _onDispose;\n\n        public Disposable(Action onDispose)\n        {\n            _onDispose = onDispose;\n        }\n        public virtual void Dispose()\n        {\n            _onDispose?.Invoke();\n            _onDispose = null;\n        }\n    }\n\n    public class Disposable<T> : Disposable\n        where T : class\n    {\n        public Disposable(T value, Action onDispose)\n            : base (onDispose)\n        {\n            Value = value;\n        }\n\n        public T Value { get; private set; }\n\n        public override void Dispose()\n        {\n            if (Value is IDisposable d)\n            {\n                d.Dispose();\n                Value = null;\n            }\n\n            base.Dispose();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/IShellState.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Input;\nusing Microsoft.Repl.Suggestions;\n\nnamespace Microsoft.Repl\n{\n    public interface IShellState\n    {\n        IInputManager InputManager { get; }\n\n        ICommandHistory CommandHistory { get; }\n\n        IConsoleManager ConsoleManager { get; }\n\n        ICommandDispatcher CommandDispatcher { get; }\n\n        ISuggestionManager SuggestionManager { get; }\n\n        bool IsExiting { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Input/AsyncKeyPressHandler.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Microsoft.Repl.Input\n{\n    public delegate Task AsyncKeyPressHandler(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken);\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Input/IInputManager.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Microsoft.Repl.Input\n{\n    public interface IInputManager\n    {\n        bool IsOverwriteMode { get; set; }\n\n        IInputManager RegisterKeyHandler(ConsoleKey key, AsyncKeyPressHandler handler);\n\n        IInputManager RegisterKeyHandler(ConsoleKey key, ConsoleModifiers modifiers, AsyncKeyPressHandler handler);\n\n        void ResetInput();\n\n        Task StartAsync(IShellState state, CancellationToken cancellationToken);\n\n        void SetInput(IShellState state, string input);\n\n        string GetCurrentBuffer();\n\n        void RemovePreviousCharacter(IShellState state);\n\n        void RemoveCurrentCharacter(IShellState state);\n\n        void Clear(IShellState state);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Input/InputManager.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Microsoft.Repl.Input\n{\n    public class InputManager : IInputManager\n    {\n        private readonly Dictionary<ConsoleKey, Dictionary<ConsoleModifiers, AsyncKeyPressHandler>> _handlers = new Dictionary<ConsoleKey, Dictionary<ConsoleModifiers, AsyncKeyPressHandler>>();\n        private readonly List<char> _inputBuffer = new List<char>();\n\n        public bool IsOverwriteMode { get; set; }\n\n        public void Clear(IShellState state)\n        {\n            SetInput(state, string.Empty);\n        }\n\n        public string GetCurrentBuffer()\n        {\n            return _inputBuffer.Stringify();\n        }\n\n        public IInputManager RegisterKeyHandler(ConsoleKey key, AsyncKeyPressHandler handler)\n        {\n            if (!_handlers.TryGetValue(key, out Dictionary<ConsoleModifiers, AsyncKeyPressHandler> handlers))\n            {\n                _handlers[key] = handlers = new Dictionary<ConsoleModifiers, AsyncKeyPressHandler>();\n            }\n\n            if (handler == null)\n            {\n                handlers.Remove(default(ConsoleModifiers));\n            }\n            else\n            {\n                handlers[default(ConsoleModifiers)] = handler;\n            }\n\n            return this;\n        }\n\n        public IInputManager RegisterKeyHandler(ConsoleKey key, ConsoleModifiers modifiers, AsyncKeyPressHandler handler)\n        {\n            if (!_handlers.TryGetValue(key, out Dictionary<ConsoleModifiers, AsyncKeyPressHandler> handlers))\n            {\n                _handlers[key] = handlers = new Dictionary<ConsoleModifiers, AsyncKeyPressHandler>();\n            }\n\n            if (handler == null)\n            {\n                handlers.Remove(modifiers);\n            }\n            else\n            {\n                handlers[modifiers] = handler;\n            }\n\n            return this;\n        }\n\n        public void RemoveCurrentCharacter(IShellState state)\n        {\n            int caret = state.ConsoleManager.CaretPosition;\n\n            if (caret == _inputBuffer.Count)\n            {\n                return;\n            }\n\n            List<char> update = _inputBuffer.ToList();\n            update.RemoveAt(caret);\n            state.ConsoleManager.IsCaretVisible = false;\n            SetInput(state, update);\n            state.ConsoleManager.MoveCaret(caret - state.ConsoleManager.CaretPosition);\n            state.ConsoleManager.IsCaretVisible = true;\n        }\n\n        public void RemovePreviousCharacter(IShellState state)\n        {\n            int caret = state.ConsoleManager.CaretPosition;\n            if (caret == 0)\n            {\n                return;\n            }\n\n            List<char> update = _inputBuffer.ToList();\n            update.RemoveAt(caret - 1);\n            state.ConsoleManager.IsCaretVisible = false;\n            SetInput(state, update, false);\n            state.ConsoleManager.MoveCaret(caret - state.ConsoleManager.CaretPosition - 1);\n            state.ConsoleManager.IsCaretVisible = true;\n        }\n\n        public void SetInput(IShellState state, string input)\n        {\n            SetInput(state, input.ToCharArray());\n        }\n\n        public void ResetInput()\n        {\n            _inputBuffer.Clear();\n        }\n\n        private string _ttyState;\n\n        private void StashEchoState()\n        {\n            string sttyFlags = null;\n            if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.OSX))\n            {\n                _ttyState = GetTtyState();\n                sttyFlags = \"gfmt1:erase=08:werase=08 -echo\";\n            }\n            //If it's any of the ubuntu variants on 18.x, stty tweaks are required\n            else if (System.Runtime.InteropServices.RuntimeInformation.OSDescription.IndexOf(\"buntu\", StringComparison.OrdinalIgnoreCase) > -1)\n            {\n                _ttyState = GetTtyState();\n                sttyFlags = \"erase 0x08 werase 0x08 -echo\";\n            }\n\n            if (!string.IsNullOrEmpty(sttyFlags))\n            {\n                ProcessStartInfo psi = new ProcessStartInfo(\"stty\", sttyFlags);\n                Process p = Process.Start(psi);\n                p?.WaitForExit();\n            }\n        }\n\n        private static string GetTtyState()\n        {\n            ProcessStartInfo psi = new ProcessStartInfo(\"stty\", \"-g\")\n            {\n                RedirectStandardOutput = true\n            };\n            Process p = Process.Start(psi);\n            p?.WaitForExit();\n            string result = p?.StandardOutput.ReadToEnd().Trim();\n            return result;\n        }\n\n        private void RestoreTtyState()\n        {\n            if (!string.IsNullOrEmpty(_ttyState))\n            {\n                ProcessStartInfo psi = new ProcessStartInfo(\"stty\", _ttyState);\n                Process p = Process.Start(psi);\n                p?.WaitForExit();\n            }\n        }\n\n        private void SetInput(IShellState state, IReadOnlyList<char> input, bool moveCaret = true)\n        {\n            bool oldCaretVisibility = state.ConsoleManager.IsCaretVisible;\n            state.ConsoleManager.IsCaretVisible = false;\n            int lastCommonPosition = 0;\n\n            for (; lastCommonPosition < input.Count && lastCommonPosition < _inputBuffer.Count && _inputBuffer[lastCommonPosition] == input[lastCommonPosition]; ++lastCommonPosition)\n            {\n            }\n\n            state.ConsoleManager.MoveCaret(-state.ConsoleManager.CaretPosition + lastCommonPosition);\n            string str = new string(input.Skip(lastCommonPosition).ToArray());\n            int trailing = _inputBuffer.Count - input.Count;\n\n            if (trailing > 0)\n            {\n                str = str.PadRight(trailing + str.Length);\n            }\n\n            state.ConsoleManager.Write(str);\n\n            if (trailing > 0 && moveCaret)\n            {\n                state.ConsoleManager.MoveCaret(-trailing);\n            }\n\n            _inputBuffer.Clear();\n            _inputBuffer.AddRange(input);\n\n            if (oldCaretVisibility)\n            {\n                state.ConsoleManager.IsCaretVisible = true;\n            }\n        }\n\n        public async Task StartAsync(IShellState state, CancellationToken cancellationToken)\n        {\n            StashEchoState();\n\n            try\n            {\n                List<ConsoleKeyInfo> presses = null;\n                while (!state.IsExiting && !cancellationToken.IsCancellationRequested)\n                {\n                    ConsoleKeyInfo keyPress = state.ConsoleManager.ReadKey(cancellationToken);\n\n                    if (_handlers.TryGetValue(keyPress.Key, out Dictionary<ConsoleModifiers, AsyncKeyPressHandler> handlerLookup) && handlerLookup.TryGetValue(keyPress.Modifiers, out AsyncKeyPressHandler handler))\n                    {\n                        using (CancellationTokenSource source = new CancellationTokenSource())\n                        using (state.ConsoleManager.AddBreakHandler(() => source.Cancel()))\n                        {\n                            if (presses != null)\n                            {\n                                FlushInput(state, ref presses);\n                            }\n\n                            await handler(keyPress, state, source.Token).ConfigureAwait(false);\n                        }\n                    }\n                    else if (!string.IsNullOrEmpty(_ttyState) && keyPress.Modifiers == ConsoleModifiers.Control)\n                    {\n                        if (presses != null)\n                        {\n                            FlushInput(state, ref presses);\n                        }\n\n                        //TODO: Verify on a mac whether these are still needed\n                        if (keyPress.Key == ConsoleKey.A)\n                        {\n                            state.ConsoleManager.MoveCaret(-state.ConsoleManager.CaretPosition);\n                        }\n                        else if (keyPress.Key == ConsoleKey.E)\n                        {\n                            state.ConsoleManager.MoveCaret(_inputBuffer.Count - state.ConsoleManager.CaretPosition);\n                        }\n                    }\n                    //TODO: Register these like regular commands\n                    else if (!string.IsNullOrEmpty(_ttyState) && keyPress.Modifiers == ConsoleModifiers.Alt)\n                    {\n                        if (presses != null)\n                        {\n                            FlushInput(state, ref presses);\n                        }\n\n                        //Move back a word\n                        if (keyPress.Key == ConsoleKey.B)\n                        {\n                            int i = state.ConsoleManager.CaretPosition - 1;\n\n                            if (i < 0)\n                            {\n                                continue;\n                            }\n\n                            bool letterMode = char.IsLetterOrDigit(_inputBuffer[i]);\n\n                            for (; i > 0 && (char.IsLetterOrDigit(_inputBuffer[i]) == letterMode); --i)\n                            {\n                            }\n\n                            if (letterMode && i > 0)\n                            {\n                                ++i;\n                            }\n\n                            if (i > -1)\n                            {\n                                state.ConsoleManager.MoveCaret(i - state.ConsoleManager.CaretPosition);\n                            }\n                        }\n                        //Move forward a word\n                        else if (keyPress.Key == ConsoleKey.F)\n                        {\n                            int i = state.ConsoleManager.CaretPosition + 1;\n\n                            if (i >= _inputBuffer.Count)\n                            {\n                                continue;\n                            }\n\n                            bool letterMode = char.IsLetterOrDigit(_inputBuffer[i]);\n\n                            for (; i < _inputBuffer.Count && (char.IsLetterOrDigit(_inputBuffer[i]) == letterMode); ++i)\n                            {\n                            }\n\n                            if (letterMode && i < _inputBuffer.Count - 1 && i > 0)\n                            {\n                                --i;\n                            }\n\n                            state.ConsoleManager.MoveCaret(i - state.ConsoleManager.CaretPosition);\n                        }\n                    }\n                    else if (!keyPress.Modifiers.HasFlag(ConsoleModifiers.Alt) && !keyPress.Modifiers.HasFlag(ConsoleModifiers.Control))\n                    {\n                        if (state.ConsoleManager.IsKeyAvailable)\n                        {\n                            if (presses == null)\n                            {\n                                presses = new List<ConsoleKeyInfo>();\n                            }\n\n                            presses.Add(keyPress);\n                            continue;\n                        }\n\n                        if (presses != null)\n                        {\n                            presses.Add(keyPress);\n                            FlushInput(state, ref presses);\n                            continue;\n                        }\n\n                        if (state.ConsoleManager.CaretPosition == _inputBuffer.Count)\n                        {\n                            _inputBuffer.Add(keyPress.KeyChar);\n                            state.ConsoleManager.Write(keyPress.KeyChar);\n                        }\n                        else if (IsOverwriteMode)\n                        {\n                            _inputBuffer[state.ConsoleManager.CaretPosition] = keyPress.KeyChar;\n                            state.ConsoleManager.Write(keyPress.KeyChar);\n                        }\n                        else\n                        {\n                            state.ConsoleManager.IsCaretVisible = false;\n                            _inputBuffer.Insert(state.ConsoleManager.CaretPosition, keyPress.KeyChar);\n                            int currentCaretPosition = state.ConsoleManager.CaretPosition;\n                            string s = new string(_inputBuffer.ToArray(), state.ConsoleManager.CaretPosition, _inputBuffer.Count - state.ConsoleManager.CaretPosition);\n                            state.ConsoleManager.Write(s);\n                            state.ConsoleManager.MoveCaret(currentCaretPosition - state.ConsoleManager.CaretPosition + 1);\n                            state.ConsoleManager.IsCaretVisible = true;\n                        }\n                    }\n                }\n            }\n            finally\n            {\n                RestoreTtyState();\n            }\n        }\n\n        private void FlushInput(IShellState state, ref List<ConsoleKeyInfo> presses)\n        {\n            string str = new string(presses.Select(x => x.KeyChar).ToArray());\n\n            if (state.ConsoleManager.CaretPosition == _inputBuffer.Count)\n            {\n                _inputBuffer.AddRange(str);\n                state.ConsoleManager.Write(str);\n            }\n            else if (IsOverwriteMode)\n            {\n                for (int i = 0; i < str.Length; ++i)\n                {\n                    if (state.ConsoleManager.CaretPosition + i < _inputBuffer.Count)\n                    {\n                        _inputBuffer[state.ConsoleManager.CaretPosition + i] = str[i];\n                    }\n                    else\n                    {\n                        _inputBuffer.AddRange(str.Skip(i));\n                        break;\n                    }\n                }\n\n                state.ConsoleManager.Write(str);\n            }\n            else\n            {\n                state.ConsoleManager.IsCaretVisible = false;\n                _inputBuffer.InsertRange(state.ConsoleManager.CaretPosition, str);\n                int currentCaretPosition = state.ConsoleManager.CaretPosition;\n                string s = new string(_inputBuffer.ToArray(), state.ConsoleManager.CaretPosition, _inputBuffer.Count - state.ConsoleManager.CaretPosition);\n                state.ConsoleManager.Write(s);\n                state.ConsoleManager.MoveCaret(currentCaretPosition - state.ConsoleManager.CaretPosition + str.Length);\n                state.ConsoleManager.IsCaretVisible = true;\n            }\n\n            presses = null;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Input/KeyHandlers.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.Repl.Input\n{\n    public static class KeyHandlers\n    {\n        public static void RegisterDefaultKeyHandlers(IInputManager inputManager)\n        {\n            //Navigation in line\n            inputManager.RegisterKeyHandler(ConsoleKey.LeftArrow, LeftArrow);\n            inputManager.RegisterKeyHandler(ConsoleKey.LeftArrow, ConsoleModifiers.Control, LeftArrow);\n            inputManager.RegisterKeyHandler(ConsoleKey.RightArrow, RightArrow);\n            inputManager.RegisterKeyHandler(ConsoleKey.RightArrow, ConsoleModifiers.Control, RightArrow);\n            inputManager.RegisterKeyHandler(ConsoleKey.Home, Home);\n            inputManager.RegisterKeyHandler(ConsoleKey.A, ConsoleModifiers.Control, Home);\n            inputManager.RegisterKeyHandler(ConsoleKey.End, End);\n            inputManager.RegisterKeyHandler(ConsoleKey.E, ConsoleModifiers.Control, End);\n\n            //Command history\n            inputManager.RegisterKeyHandler(ConsoleKey.UpArrow, UpArrow);\n            inputManager.RegisterKeyHandler(ConsoleKey.DownArrow, DownArrow);\n\n            //Completion\n            inputManager.RegisterKeyHandler(ConsoleKey.Tab, Tab);\n            inputManager.RegisterKeyHandler(ConsoleKey.Tab, ConsoleModifiers.Shift, Tab);\n\n            //Input manipulation\n            inputManager.RegisterKeyHandler(ConsoleKey.Escape, Escape);\n            inputManager.RegisterKeyHandler(ConsoleKey.U, ConsoleModifiers.Control, Escape);\n            inputManager.RegisterKeyHandler(ConsoleKey.Delete, Delete);\n            inputManager.RegisterKeyHandler(ConsoleKey.Backspace, Backspace);\n\n            //Insert/Overwrite mode\n            inputManager.RegisterKeyHandler(ConsoleKey.Insert, Insert);\n\n            //Execute command\n            inputManager.RegisterKeyHandler(ConsoleKey.Enter, Enter);\n\n            //Map non-printable keys that aren't handled by default\n            inputManager.RegisterKeyHandler(ConsoleKey.F1, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F2, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F3, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F4, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F5, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F6, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F7, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F8, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F9, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F10, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F11, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F12, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F13, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F14, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F15, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F16, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F17, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F18, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F19, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F20, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F21, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F22, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F23, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.F24, Unhandled);\n\n            inputManager.RegisterKeyHandler(ConsoleKey.Applications, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.Attention, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.BrowserBack, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.BrowserFavorites, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.BrowserForward, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.BrowserHome, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.BrowserRefresh, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.BrowserSearch, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.BrowserStop, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.Clear, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.CrSel, Unhandled);\n\n            inputManager.RegisterKeyHandler(ConsoleKey.EraseEndOfFile, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.Execute, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.ExSel, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.Help, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.LaunchApp1, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.LaunchApp2, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.LaunchMail, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.LaunchMediaSelect, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.LeftWindows, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.MediaNext, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.MediaPlay, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.MediaPrevious, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.MediaStop, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.NoName, Unhandled);\n\n            inputManager.RegisterKeyHandler(ConsoleKey.Pa1, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.Packet, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.PageDown, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.PageUp, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.Pause, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.Play, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.Print, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.PrintScreen, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.Process, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.RightWindows, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.Select, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.Separator, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.Sleep, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.VolumeDown, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.VolumeMute, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.VolumeUp, Unhandled);\n            inputManager.RegisterKeyHandler(ConsoleKey.Zoom, Unhandled);\n        }\n\n        private static Task End(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken)\n        {\n            state.ConsoleManager.MoveCaret(state.InputManager.GetCurrentBuffer().Length - state.ConsoleManager.CaretPosition);\n            return Task.CompletedTask;\n        }\n\n        public static Task Home(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken)\n        {\n            state.ConsoleManager.MoveCaret(-state.ConsoleManager.CaretPosition);\n            return Task.CompletedTask;\n        }\n\n        public static Task LeftArrow(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken)\n        {\n            if (state.ConsoleManager.CaretPosition > 0)\n            {\n                if (!keyInfo.Modifiers.HasFlag(ConsoleModifiers.Control))\n                {\n                    state.ConsoleManager.MoveCaret(-1);\n                }\n                else\n                {\n                    string line = state.InputManager.GetCurrentBuffer();\n                    ICoreParseResult parseResult = state.CommandDispatcher.Parser.Parse(line, state.ConsoleManager.CaretPosition);\n                    int targetSection = parseResult.SelectedSection - (parseResult.CaretPositionWithinSelectedSection > 0 ? 0 : 1);\n\n                    if (targetSection < 0)\n                    {\n                        targetSection = 0;\n                    }\n\n                    int desiredPosition = parseResult.SectionStartLookup[targetSection];\n                    state.ConsoleManager.MoveCaret(desiredPosition - state.ConsoleManager.CaretPosition);\n                }\n            }\n\n            return Task.CompletedTask;\n        }\n\n        public static Task RightArrow(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken)\n        {\n            string line = state.InputManager.GetCurrentBuffer();\n\n            if (state.ConsoleManager.CaretPosition < line.Length)\n            {\n                if (!keyInfo.Modifiers.HasFlag(ConsoleModifiers.Control))\n                {\n                    state.ConsoleManager.MoveCaret(1);\n                }\n                else\n                {\n                    ICoreParseResult parseResult = state.CommandDispatcher.Parser.Parse(line, state.ConsoleManager.CaretPosition);\n                    int targetSection = parseResult.SelectedSection + 1;\n\n                    if (targetSection >= parseResult.Sections.Count)\n                    {\n                        state.ConsoleManager.MoveCaret(line.Length - state.ConsoleManager.CaretPosition);\n                    }\n                    else\n                    {\n                        int desiredPosition = parseResult.SectionStartLookup[targetSection];\n                        state.ConsoleManager.MoveCaret(desiredPosition - state.ConsoleManager.CaretPosition);\n                    }\n                }\n            }\n\n            return Task.CompletedTask;\n        }\n\n        public static Task UpArrow(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken)\n        {\n            string line = state.CommandHistory.GetPreviousCommand();\n            state.InputManager.SetInput(state, line);\n            return Task.CompletedTask;\n        }\n\n        public static Task DownArrow(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken)\n        {\n            string line = state.CommandHistory.GetNextCommand();\n            state.InputManager.SetInput(state, line);\n            return Task.CompletedTask;\n        }\n\n        public static Task Enter(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken)\n        {\n            return state.CommandDispatcher.ExecuteCommandAsync(state, cancellationToken);\n        }\n\n        public static Task Backspace(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken)\n        {\n            state.InputManager.RemovePreviousCharacter(state);\n            return Task.CompletedTask;\n        }\n\n        public static Task Unhandled(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken)\n        {\n            return Task.CompletedTask;\n        }\n\n        public static Task Escape(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken)\n        {\n            state.InputManager.SetInput(state, string.Empty);\n            return Task.CompletedTask;\n        }\n\n        public static Task Tab(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken)\n        {\n            if (keyInfo.Modifiers.HasFlag(ConsoleModifiers.Shift))\n            {\n                state.SuggestionManager.PreviousSuggestion(state);\n            }\n            else\n            {\n                state.SuggestionManager.NextSuggestion(state);\n            }\n\n            return Task.CompletedTask;\n        }\n\n        public static Task Delete(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken)\n        {\n            state.InputManager.RemoveCurrentCharacter(state);\n            return Task.CompletedTask;\n        }\n\n        public static Task Insert(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken)\n        {\n            state.InputManager.IsOverwriteMode = !state.InputManager.IsOverwriteMode;\n            return Task.CompletedTask;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Microsoft.Repl.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n    <Description>A framework for creating REPLs in .NET Core.</Description>\n    <PackageTags>dotnet;repl</PackageTags>\n    <IsPackable>false</IsPackable>\n  </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "src/Microsoft.Repl/Parsing/CoreParseResult.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Microsoft.Repl.Parsing\n{\n    public class CoreParseResult : ICoreParseResult\n    {\n        public CoreParseResult(int caretPositionWithinCommandText, int caretPositionWithinSelectedSection, string commandText, IReadOnlyList<string> sections, int selectedSection, IReadOnlyDictionary<int, int> sectionStartLookup, HashSet<int> quotedSections)\n        {\n            CaretPositionWithinCommandText = caretPositionWithinCommandText;\n            CaretPositionWithinSelectedSection = caretPositionWithinSelectedSection;\n            CommandText = commandText;\n            Sections = sections;\n            SelectedSection = selectedSection;\n            SectionStartLookup = sectionStartLookup;\n            _quotedSections = quotedSections;\n        }\n\n        public int CaretPositionWithinCommandText { get; }\n\n        public int CaretPositionWithinSelectedSection { get; }\n\n        public string CommandText { get; }\n\n        public IReadOnlyList<string> Sections { get; }\n\n        public int SelectedSection { get; }\n\n        public IReadOnlyDictionary<int, int> SectionStartLookup { get; }\n\n        private readonly HashSet<int> _quotedSections;\n\n        public bool IsQuotedSection(int index)\n        {\n            return _quotedSections.Contains(index);\n        }\n\n        public virtual ICoreParseResult Slice(int numberOfLeadingSectionsToRemove)\n        {\n            if (numberOfLeadingSectionsToRemove == 0)\n            {\n                return this;\n            }\n\n            if (numberOfLeadingSectionsToRemove >= Sections.Count)\n            {\n                return new CoreParseResult(0, 0, string.Empty, new[] { string.Empty }, 0, new Dictionary<int, int> { { 0, 0 } }, new HashSet<int>());\n            }\n\n            string commandText = CommandText.Substring(SectionStartLookup[numberOfLeadingSectionsToRemove]);\n            int caretPositionWithinCommandText = CaretPositionWithinCommandText - SectionStartLookup[numberOfLeadingSectionsToRemove];\n\n            if (caretPositionWithinCommandText < 0)\n            {\n                caretPositionWithinCommandText = 0;\n            }\n\n            Dictionary<int, int> sectionStartLookup = new Dictionary<int, int>();\n            List<string> sections = new List<string>();\n            for (int i = 0; i < Sections.Count - numberOfLeadingSectionsToRemove; ++i)\n            {\n                sectionStartLookup[i] = SectionStartLookup[numberOfLeadingSectionsToRemove + i] - SectionStartLookup[numberOfLeadingSectionsToRemove];\n                sections.Add(Sections[numberOfLeadingSectionsToRemove + i]);\n            }\n\n            int selectedSection = SelectedSection - numberOfLeadingSectionsToRemove;\n\n            if (selectedSection < 0)\n            {\n                selectedSection = 0;\n            }\n\n            HashSet<int> quotedSections = new HashSet<int>(_quotedSections.Where(x => x > 0).Select(x => x - 1));\n            return new CoreParseResult(caretPositionWithinCommandText, CaretPositionWithinSelectedSection, commandText, sections, selectedSection, sectionStartLookup, quotedSections);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Parsing/CoreParser.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Microsoft.Repl.Parsing\n{\n    public class CoreParser : IParser<ICoreParseResult>\n    {\n        public ICoreParseResult Parse(string commandText, int caretPosition)\n        {\n            List<string> sections = commandText.Split(' ').ToList();\n            Dictionary<int, int> sectionStartLookup = new Dictionary<int, int>();\n            HashSet<int> quotedSections = new HashSet<int>();\n            int runningIndex = 0;\n            int selectedSection = -1;\n            int caretPositionWithinSelectedSection = 0;\n            bool isInQuotedSection = false;\n\n            for (int i = 0; i < sections.Count; ++i)\n            {\n                int thisSectionLength = sections[i].Length;\n                bool isLastSection = i == sections.Count - 1;\n\n                //If currently in a quoted section, combine with the previous section, check to see if this section closes the quotes\n                if (isInQuotedSection)\n                {\n                    //Combine with the previous section\n                    sections[i - 1] += \" \" + sections[i];\n                    sections.RemoveAt(i--);\n\n                    //Check for the closing quote\n                    int sectionLength = sections[i].Length;\n                    if (sections[i][sectionLength - 1] == '\"')\n                    {\n                        if (sectionLength > 1 && sections[i][sectionLength - 2] != '\\\\')\n                        {\n                            isInQuotedSection = false;\n                        }\n                    }\n                }\n                //Not in a quoted section, check to see if we're starting one\n                else\n                {\n                    sectionStartLookup[i] = runningIndex;\n\n                    if (sections[i].Length > 0)\n                    {\n                        if (sections[i][0] == '\"')\n                        {\n                            isInQuotedSection = true;\n                        }\n                    }\n                }\n\n                //Update the running index, adding one for all but the last element to account for the spaces between the sections\n                runningIndex += thisSectionLength + (isLastSection ? 0 : 1);\n\n                //If the selected section hasn't been determined yet, and the end of the text is past the caret, set the selected\n                //  section to the current section and set the initial value for the caret position within the selected section.\n                //  Note that the caret position within the selected section, unlike the other positions, accounts for escape\n                //  sequences and must be fixed up when escape sequences are removed\n                if (selectedSection == -1 && runningIndex > caretPosition)\n                {\n                    selectedSection = i;\n                    caretPositionWithinSelectedSection = caretPosition - sectionStartLookup[i];\n                }\n            }\n\n            //Unescape the sections\n            //  Note that this isn't combined with the above loop to avoid additional complexity in the quoted section case\n            for (int i = 0; i < sections.Count; ++i)\n            {\n                string s = sections[i];\n\n                //Trim quotes if needed\n                if (s.Length > 1)\n                {\n                    if (s[0] == s[s.Length - 1] && s[0] == '\"')\n                    {\n                        s = s.Substring(1, s.Length - 2);\n                        quotedSections.Add(i);\n\n                        //Fix up the caret position in the text\n                        if (selectedSection == i)\n                        {\n                            //If the caret was on the closing quote, back up to the last character of the section\n                            if (caretPositionWithinSelectedSection == s.Length - 1)\n                            {\n                                caretPositionWithinSelectedSection -= 2;\n                            }\n                            //If the caret was after the opening quote, back up one\n                            else if (caretPositionWithinSelectedSection > 0)\n                            {\n                                --caretPositionWithinSelectedSection;\n                            }\n                        }\n                    }\n                }\n\n                for (int j = 0; j < s.Length - 1; ++j)\n                {\n                    if (s[j] == '\\\\')\n                    {\n                        if (s[j + 1] == '\\\\' || s[j + 1] == '\"')\n                        {\n                            s = s.Substring(0, j) + s.Substring(j + 1);\n\n                            //If we're changing the selected section, and we're removing a character\n                            //  from before the caret position, back the caret position up to account for it\n                            if (selectedSection == i && j < caretPositionWithinSelectedSection)\n                            {\n                                --caretPositionWithinSelectedSection;\n                            }\n                        }\n                    }\n                }\n\n                sections[i] = s;\n            }\n\n            if (selectedSection == -1)\n            {\n                selectedSection = sections.Count - 1;\n                caretPositionWithinSelectedSection = sections[selectedSection].Length;\n            }\n\n            return new CoreParseResult(caretPosition, caretPositionWithinSelectedSection, commandText, sections, selectedSection, sectionStartLookup, quotedSections);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Parsing/ICoreParseResult.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.Repl.Parsing\n{\n    public interface ICoreParseResult\n    {\n        int CaretPositionWithinCommandText { get; }\n\n        int CaretPositionWithinSelectedSection { get; }\n\n        string CommandText { get; }\n\n        IReadOnlyList<string> Sections { get; }\n\n        bool IsQuotedSection(int index);\n\n        int SelectedSection { get; }\n\n        IReadOnlyDictionary<int, int> SectionStartLookup { get; }\n\n        ICoreParseResult Slice(int numberOfLeadingSectionsToRemove);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Parsing/IParser.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.Repl.Parsing\n{\n    public interface IParser\n    {\n        ICoreParseResult Parse(string commandText, int caretPosition);\n    }\n\n    public interface IParser<out TParseResult> : IParser\n    {\n        new TParseResult Parse(string commandText, int caretPosition);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Scripting/IScriptExecutor.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Microsoft.Repl.Scripting\n{\n    public interface IScriptExecutor\n    {\n        Task ExecuteScriptAsync(IShellState shellState, IEnumerable<string> commandTexts, CancellationToken cancellationToken);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Scripting/ScriptExecutor.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.Repl.Scripting\n{\n    public class ScriptExecutor<TProgramState, TParseResult> : IScriptExecutor\n        where TParseResult : ICoreParseResult\n    {\n        private readonly bool _hideScriptLinesFromHistory;\n\n        public ScriptExecutor(bool hideScriptLinesFromHistory = true)\n        {\n            _hideScriptLinesFromHistory = hideScriptLinesFromHistory;\n        }\n\n        public async Task ExecuteScriptAsync(IShellState shellState, IEnumerable<string> commandTexts, CancellationToken cancellationToken)\n        {\n            if (shellState.CommandDispatcher is ICommandDispatcher<TProgramState, TParseResult> dispatcher)\n            {\n                IDisposable suppressor = _hideScriptLinesFromHistory ? shellState.CommandHistory.SuspendHistory() : null;\n\n                using (suppressor)\n                {\n                    foreach (string commandText in commandTexts)\n                    {\n                        if (string.IsNullOrWhiteSpace(commandText))\n                        {\n                            continue;\n                        }\n\n                        if (cancellationToken.IsCancellationRequested)\n                        {\n                            break;\n                        }\n\n                        dispatcher.OnReady(shellState);\n                        shellState.ConsoleManager.ResetCommandStart();\n                        shellState.InputManager.SetInput(shellState, commandText);\n                        await dispatcher.ExecuteCommandAsync(shellState, cancellationToken).ConfigureAwait(false);\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Shell.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.Input;\nusing Microsoft.Repl.Suggestions;\n\nnamespace Microsoft.Repl\n{\n    public class Shell\n    {\n        public Shell(IShellState shellState)\n        {\n            KeyHandlers.RegisterDefaultKeyHandlers(shellState.InputManager);\n            ShellState = shellState;\n        }\n\n        public Shell(ICommandDispatcher dispatcher, ISuggestionManager suggestionManager = null)\n            : this(new ShellState(dispatcher, suggestionManager))\n        {\n        }\n\n        public IShellState ShellState { get; }\n\n        public Task RunAsync(CancellationToken cancellationToken)\n        {\n            ShellState.CommandDispatcher.OnReady(ShellState);\n            return ShellState.InputManager.StartAsync(ShellState, cancellationToken);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/ShellState.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.Repl.Commanding;\nusing Microsoft.Repl.ConsoleHandling;\nusing Microsoft.Repl.Input;\nusing Microsoft.Repl.Suggestions;\n\nnamespace Microsoft.Repl\n{\n    public class ShellState : IShellState\n    {\n        public ShellState(ICommandDispatcher commandDispatcher, ISuggestionManager suggestionManager = null, IInputManager inputManager = null, ICommandHistory commandHistory = null, IConsoleManager consoleManager = null)\n        {\n            InputManager = inputManager ?? new InputManager();\n            CommandHistory = commandHistory ?? new CommandHistory();\n            ConsoleManager = consoleManager ?? new ConsoleManager();\n            CommandDispatcher = commandDispatcher;\n            SuggestionManager = suggestionManager ?? new SuggestionManager();\n        }\n\n        public IInputManager InputManager { get; }\n\n        public ICommandHistory CommandHistory { get; }\n\n        public IConsoleManager ConsoleManager { get; }\n\n        public ICommandDispatcher CommandDispatcher { get; }\n\n        public bool IsExiting { get; set; }\n\n        public ISuggestionManager SuggestionManager { get; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Suggestions/FileSystemCompletion.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\n\nnamespace Microsoft.Repl.Suggestions\n{\n    public static class FileSystemCompletion\n    {\n        public static IEnumerable<string> GetCompletions(string prefix)\n        {\n            if (prefix.StartsWith('\\\"'))\n            {\n                prefix = prefix.Substring(1);\n\n                int lastQuote = prefix.LastIndexOf('\\\"');\n\n                if (lastQuote > -1)\n                {\n                    prefix = prefix.Remove(lastQuote, 1);\n                }\n\n                while (prefix.EndsWith($\"{Path.DirectorySeparatorChar}{Path.DirectorySeparatorChar}\"))\n                {\n                    prefix = prefix.Substring(0, prefix.Length - 1);\n                }\n            }\n\n            int lastPathIndex = prefix.LastIndexOfAny(new[] { '\\\\', '/' });\n            if (lastPathIndex < 0)\n            {\n                return null;\n            }\n\n            string dir = prefix.Substring(0, lastPathIndex + 1);\n\n            if (dir.IndexOfAny(Path.GetInvalidPathChars()) > -1)\n            {\n                return null;\n            }\n\n            string partPrefix = prefix.Substring(lastPathIndex + 1);\n            if (Directory.Exists(dir))\n            {\n                return Directory.EnumerateDirectories(dir).Where(x => Path.GetFileName(x).StartsWith(partPrefix, StringComparison.OrdinalIgnoreCase))\n                    .Union(Directory.EnumerateFiles(dir).Where(x => Path.GetFileName(x).StartsWith(partPrefix, StringComparison.OrdinalIgnoreCase))).Select(x => x.IndexOf(' ') > -1 ? $\"\\\"{x}\\\"\" : x);\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Suggestions/ISuggestionManager.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.Repl.Suggestions\n{\n    public interface ISuggestionManager\n    {\n        void NextSuggestion(IShellState shellState);\n\n        void PreviousSuggestion(IShellState shellState);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Suggestions/SuggestionManager.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing Microsoft.Repl.Parsing;\n\nnamespace Microsoft.Repl.Suggestions\n{\n    public class SuggestionManager : ISuggestionManager\n    {\n        private int _currentSuggestion;\n        private IReadOnlyList<string> _suggestions;\n        private ICoreParseResult _expected;\n\n        public void NextSuggestion(IShellState shellState)\n        {\n            string line = shellState.InputManager.GetCurrentBuffer();\n            ICoreParseResult parseResult = shellState.CommandDispatcher.Parser.Parse(line, shellState.ConsoleManager.CaretPosition);\n            string currentSuggestion;\n\n            //Check to see if we're continuing before querying for suggestions again\n            if (_expected != null\n                && string.Equals(_expected.CommandText, parseResult.CommandText, StringComparison.Ordinal)\n                && _expected.SelectedSection == parseResult.SelectedSection\n                && _expected.CaretPositionWithinSelectedSection == parseResult.CaretPositionWithinSelectedSection)\n            {\n                if (_suggestions == null || _suggestions.Count == 0)\n                {\n                    return;\n                }\n\n                _currentSuggestion = (_currentSuggestion + 1) % _suggestions.Count;\n                currentSuggestion = _suggestions[_currentSuggestion];\n            }\n            else\n            {\n                _currentSuggestion = 0;\n                _suggestions = shellState.CommandDispatcher.CollectSuggestions(shellState);\n\n                if (_suggestions == null || _suggestions.Count == 0)\n                {\n                    return;\n                }\n\n                currentSuggestion = _suggestions[0];\n            }\n\n            //We now have a suggestion, take the command text leading up to the section being suggested for,\n            //  concatenate that and the suggestion text, turn it in to keys, submit it to the input manager,\n            //  reset the caret, store the parse result of the new text as what's expected for a continuation\n            string newText = parseResult.CommandText.Substring(0, parseResult.SectionStartLookup[parseResult.SelectedSection]) + currentSuggestion;\n            _expected = shellState.CommandDispatcher.Parser.Parse(newText, newText.Length);\n            shellState.InputManager.SetInput(shellState, newText);\n        }\n\n        public void PreviousSuggestion(IShellState shellState)\n        {\n            string line = shellState.InputManager.GetCurrentBuffer();\n            ICoreParseResult parseResult = shellState.CommandDispatcher.Parser.Parse(line, shellState.ConsoleManager.CaretPosition);\n            string currentSuggestion;\n\n            //Check to see if we're continuing before querying for suggestions again\n            if (_expected != null\n                && string.Equals(_expected.CommandText, parseResult.CommandText, StringComparison.Ordinal)\n                && _expected.SelectedSection == parseResult.SelectedSection\n                && _expected.CaretPositionWithinSelectedSection == parseResult.CaretPositionWithinSelectedSection)\n            {\n                if (_suggestions == null || _suggestions.Count == 0)\n                {\n                    return;\n                }\n\n                _currentSuggestion = (_currentSuggestion - 1 + _suggestions.Count) % _suggestions.Count;\n                currentSuggestion = _suggestions[_currentSuggestion];\n            }\n            else\n            {\n                _suggestions = shellState.CommandDispatcher.CollectSuggestions(shellState);\n                _currentSuggestion = _suggestions.Count - 1;\n\n                if (_suggestions == null || _suggestions.Count == 0)\n                {\n                    return;\n                }\n\n                currentSuggestion = _suggestions[_suggestions.Count - 1];\n            }\n\n            //We now have a suggestion, take the command text leading up to the section being suggested for,\n            //  concatenate that and the suggestion text, turn it in to keys, submit it to the input manager,\n            //  reset the caret, store the parse result of the new text as what's expected for a continuation\n            string newText = parseResult.CommandText.Substring(0, parseResult.SectionStartLookup[parseResult.SelectedSection]) + currentSuggestion;\n            _expected = shellState.CommandDispatcher.Parser.Parse(newText, newText.Length);\n            shellState.InputManager.SetInput(shellState, newText);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.Repl/Utils.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.Repl\n{\n    public static class Utils\n    {\n        public static string Stringify(this IReadOnlyList<char> keys)\n        {\n            return string.Join(\"\", keys);\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-dev-certs/Program.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Security.Cryptography.X509Certificates;\nusing Microsoft.AspNetCore.Certificates.Generation;\nusing Microsoft.Extensions.CommandLineUtils;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.AspNetCore.DeveloperCertificates.Tools\n{\n    internal class Program\n    {\n        private const int CriticalError = -1;\n        private const int Success = 0;\n        private const int ErrorCreatingTheCertificate = 1;\n        private const int ErrorSavingTheCertificate = 2;\n        private const int ErrorExportingTheCertificate = 3;\n        private const int ErrorTrustingTheCertificate = 4;\n        private const int ErrorUserCancelledTrustPrompt = 5;\n        private const int ErrorNoValidCertificateFound = 6;\n        private const int ErrorCertificateNotTrusted = 7;\n        private const int ErrorCleaningUpCertificates = 8;\n\n        public static readonly TimeSpan HttpsCertificateValidity = TimeSpan.FromDays(365);\n\n        public static int Main(string[] args)\n        {\n            try\n            {\n                var app = new CommandLineApplication\n                {\n                    Name = \"dotnet dev-certs\"\n                };\n\n                app.Command(\"https\", c =>\n                {\n                    var exportPath = c.Option(\"-ep|--export-path\",\n                        \"Full path to the exported certificate\",\n                        CommandOptionType.SingleValue);\n\n                    var password = c.Option(\"-p|--password\",\n                        \"Password to use when exporting the certificate with the private key into a pfx file\",\n                        CommandOptionType.SingleValue);\n\n                    var check = c.Option(\n                        \"-c|--check\",\n                        \"Check for the existence of the certificate but do not perform any action\",\n                        CommandOptionType.NoValue);\n\n                    var clean = c.Option(\n                        \"--clean\",\n                        \"Cleans all HTTPS development certificates from the machine.\",\n                        CommandOptionType.NoValue);\n\n                    CommandOption trust = null;\n                    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))\n                    {\n                        trust = c.Option(\"-t|--trust\",\n                            \"Trust the certificate on the current platform\",\n                            CommandOptionType.NoValue);\n                    }\n\n                    var verbose = c.Option(\"-v|--verbose\",\n                        \"Display more debug information.\",\n                        CommandOptionType.NoValue);\n\n                    var quiet = c.Option(\"-q|--quiet\",\n                        \"Display warnings and errors only.\",\n                        CommandOptionType.NoValue);\n\n                    c.HelpOption(\"-h|--help\");\n\n                    c.OnExecute(() =>\n                    {\n                        var reporter = new ConsoleReporter(PhysicalConsole.Singleton, verbose.HasValue(), quiet.HasValue());\n                        if ((clean.HasValue() && (exportPath.HasValue() || password.HasValue() || trust?.HasValue() == true)) ||\n                            (check.HasValue() && (exportPath.HasValue() || password.HasValue() || clean.HasValue())))\n                        {\n                            reporter.Error(@\"Incompatible set of flags. Sample usages\n'dotnet dev-certs https --clean'\n'dotnet dev-certs https --check --trust'\n'dotnet dev-certs https -ep ./certificate.pfx -p password --trust'\");\n                        }\n\n                        if (check.HasValue())\n                        {\n                            return CheckHttpsCertificate(trust, reporter);\n                        }\n\n                        if (clean.HasValue())\n                        {\n                            return CleanHttpsCertificates(reporter);\n                        }\n\n                        return EnsureHttpsCertificate(exportPath, password, trust, reporter);\n                    });\n                });\n\n                app.HelpOption(\"-h|--help\");\n\n                app.OnExecute(() =>\n                    {\n                        app.ShowHelp();\n                        return Success;\n                    });\n\n                return app.Execute(args);\n            }\n            catch\n            {\n                return CriticalError;\n            }\n        }\n\n        private static int CleanHttpsCertificates(IReporter reporter)\n        {\n            var manager = new CertificateManager();\n            try\n            {\n                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))\n                {\n                    reporter.Output(\"Cleaning HTTPS development certificates from the machine. A prompt might get \" +\n                        \"displayed to confirm the removal of some of the certificates.\");\n                }\n                if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))\n                {\n                    reporter.Output(\"Cleaning HTTPS development certificates from the machine. This operation might \" +\n                        \"require elevated privileges. If that is the case, a prompt for credentials will be displayed.\");\n                }\n\n                manager.CleanupHttpsCertificates();\n                reporter.Verbose(\"HTTPS development certificates successfully removed from the machine.\");\n                return Success;\n            }\n            catch(Exception e)\n            {\n                reporter.Error(\"There was an error trying to clean HTTPS development certificates on this machine.\");\n                reporter.Error(e.Message);\n\n                return ErrorCleaningUpCertificates;\n            }\n        }\n\n        private static int CheckHttpsCertificate(CommandOption trust, IReporter reporter)\n        {\n            var now = DateTimeOffset.Now;\n            var certificateManager = new CertificateManager();\n            var certificates = certificateManager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: true);\n            if (certificates.Count == 0)\n            {\n                reporter.Verbose(\"No valid certificate found.\");\n                return ErrorNoValidCertificateFound;\n            }\n            else\n            {\n                reporter.Verbose(\"A valid certificate was found.\");\n            }\n\n            if (trust != null && trust.HasValue())\n            {\n                var store = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? StoreName.My : StoreName.Root;\n                var trustedCertificates = certificateManager.ListCertificates(CertificatePurpose.HTTPS, store, StoreLocation.CurrentUser, isValid: true);\n                if (!certificates.Any(c => certificateManager.IsTrusted(c)))\n                {\n                    reporter.Verbose($@\"The following certificates were found, but none of them is trusted:\n{string.Join(Environment.NewLine, certificates.Select(c => $\"{c.Subject} - {c.Thumbprint}\"))}\");\n                    return ErrorCertificateNotTrusted;\n                }\n                else\n                {\n                    reporter.Verbose(\"A trusted certificate was found.\");\n                }\n            }\n\n            return Success;\n        }\n\n        private static int EnsureHttpsCertificate(CommandOption exportPath, CommandOption password, CommandOption trust, IReporter reporter)\n        {\n            var now = DateTimeOffset.Now;\n            var manager = new CertificateManager();\n\n            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && trust?.HasValue() == true)\n            {\n                reporter.Warn(\"Trusting the HTTPS development certificate was requested. If the certificate is not \" +\n                    \"already trusted we will run the following command:\" + Environment.NewLine +\n                    \"'sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <<certificate>>'\" +\n                    Environment.NewLine + \"This command might prompt you for your password to install the certificate \" +\n                    \"on the system keychain.\");\n            }\n\n            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && trust?.HasValue() == true)\n            {\n                reporter.Warn(\"Trusting the HTTPS development certificate was requested. A confirmation prompt will be displayed \" +\n                    \"if the certificate was not previously trusted. Click yes on the prompt to trust the certificate.\");\n            }\n\n            var result = manager.EnsureAspNetCoreHttpsDevelopmentCertificate(\n                now,\n                now.Add(HttpsCertificateValidity),\n                exportPath.Value(),\n                trust == null ? false : trust.HasValue(),\n                password.HasValue(),\n                password.Value());\n\n            switch (result)\n            {\n                case EnsureCertificateResult.Succeeded:\n                    reporter.Output(\"The HTTPS developer certificate was generated successfully.\");\n                    if (exportPath.Value() != null)\n                    {\n                        reporter.Verbose($\"The certificate was exported to {Path.GetFullPath(exportPath.Value())}\");\n                    }\n                    return Success;\n                case EnsureCertificateResult.ValidCertificatePresent:\n                    reporter.Output(\"A valid HTTPS certificate is already present.\");\n                    if (exportPath.Value() != null)\n                    {\n                        reporter.Verbose($\"The certificate was exported to {Path.GetFullPath(exportPath.Value())}\");\n                    }\n                    return Success;\n                case EnsureCertificateResult.ErrorCreatingTheCertificate:\n                    reporter.Error(\"There was an error creating the HTTPS developer certificate.\");\n                    return ErrorCreatingTheCertificate;\n                case EnsureCertificateResult.ErrorSavingTheCertificateIntoTheCurrentUserPersonalStore:\n                    reporter.Error(\"There was an error saving the HTTPS developer certificate to the current user personal certificate store.\");\n                    return ErrorSavingTheCertificate;\n                case EnsureCertificateResult.ErrorExportingTheCertificate:\n                    reporter.Warn(\"There was an error exporting HTTPS developer certificate to a file.\");\n                    return ErrorExportingTheCertificate;\n                case EnsureCertificateResult.FailedToTrustTheCertificate:\n                    reporter.Warn(\"There was an error trusting HTTPS developer certificate.\");\n                    return ErrorTrustingTheCertificate;\n                case EnsureCertificateResult.UserCancelledTrustStep:\n                    reporter.Warn(\"The user cancelled the trust step.\");\n                    return ErrorUserCancelledTrustPrompt;\n                default:\n                    reporter.Error(\"Something went wrong. The HTTPS developer certificate could not be created.\");\n                    return CriticalError;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-dev-certs/README.md",
    "content": "dotnet-dev-certs\n================\n\n`dotnet-dev-certs` is a command line tool to generate certificates used in ASP.NET Core during development.\n\n### How To Use\n\nRun `dotnet dev-certs --help` for more information about usage.\n"
  },
  {
    "path": "src/dotnet-dev-certs/dotnet-dev-certs.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n    <OutputType>exe</OutputType>\n    <Description>Command line tool to generate certificates used in ASP.NET Core during development.</Description>\n    <RootNamespace>Microsoft.AspNetCore.DeveloperCertificates.Tools</RootNamespace>\n    <PackageTags>dotnet;developercertificates</PackageTags>\n    <PackAsTool>true</PackAsTool>\n    <!-- This is a requirement for Microsoft tool packages only. -->\n    <PackAsToolShimRuntimeIdentifiers>win-x64;win-x86</PackAsToolShimRuntimeIdentifiers>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Compile Include=\"..\\..\\shared\\CliContext.cs\" Link=\"CliContext.cs\" />\n    <Compile Include=\"..\\..\\shared\\CommandLineApplicationExtensions.cs\" Link=\"CommandLineApplicationExtensions.cs\" />\n    <Compile Include=\"..\\..\\shared\\ConsoleReporter.cs\" Link=\"ConsoleReporter.cs\" />\n    <Compile Include=\"..\\..\\shared\\DebugHelper.cs\" Link=\"DebugHelper.cs\" />\n    <Compile Include=\"..\\..\\shared\\Ensure.cs\" Link=\"Ensure.cs\" />\n    <Compile Include=\"..\\..\\shared\\IConsole.cs\" Link=\"IConsole.cs\" />\n    <Compile Include=\"..\\..\\shared\\IReporter.cs\" Link=\"IReporter.cs\" />\n    <Compile Include=\"..\\..\\shared\\NullReporter.cs\" Link=\"NullReporter.cs\" />\n    <Compile Include=\"..\\..\\shared\\PhysicalConsole.cs\" Link=\"PhysicalConsole.cs\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Certificates.Generation.Sources\" PrivateAssets=\"All\" Version=\"$(MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.CommandLineUtils.Sources\" PrivateAssets=\"All\" Version=\"$(MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion)\" />\n    <PackageReference Include=\"System.Security.Cryptography.Cng\" Version=\"$(SystemSecurityCryptographyCngPackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/dotnet-sql-cache/Program.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Data;\nusing System.Data.SqlClient;\nusing System.Reflection;\nusing Microsoft.Extensions.CommandLineUtils;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.Extensions.Caching.SqlConfig.Tools\n{\n    public class Program\n    {\n        private string _connectionString = null;\n        private string _schemaName = null;\n        private string _tableName = null;\n        private readonly IConsole _console;\n\n        public Program(IConsole console)\n        {\n            Ensure.NotNull(console, nameof(console));\n\n            _console = console;\n        }\n\n        public static int Main(string[] args)\n        {\n            return new Program(PhysicalConsole.Singleton).Run(args);\n        }\n\n        public int Run(string[] args)\n        {\n            DebugHelper.HandleDebugSwitch(ref args);\n\n            try\n            {\n                var app = new CommandLineApplication\n                {\n                    Name = \"dotnet sql-cache\",\n                    FullName = \"SQL Server Cache Command Line Tool\",\n                    Description =\n                        \"Creates table and indexes in Microsoft SQL Server database to be used for distributed caching\",\n                };\n\n                app.HelpOption();\n                app.VersionOptionFromAssemblyAttributes(typeof(Program).GetTypeInfo().Assembly);\n                var verbose = app.VerboseOption();\n\n                app.Command(\"create\", command =>\n                {\n                    command.Description = app.Description;\n\n                    var connectionStringArg = command.Argument(\n                        \"[connectionString]\", \"The connection string to connect to the database.\");\n\n                    var schemaNameArg = command.Argument(\n                        \"[schemaName]\", \"Name of the table schema.\");\n\n                    var tableNameArg = command.Argument(\n                        \"[tableName]\", \"Name of the table to be created.\");\n\n                    command.HelpOption();\n\n                    command.OnExecute(() =>\n                    {\n                        var reporter = CreateReporter(verbose.HasValue());\n                        if (string.IsNullOrEmpty(connectionStringArg.Value)\n                            || string.IsNullOrEmpty(schemaNameArg.Value)\n                            || string.IsNullOrEmpty(tableNameArg.Value))\n                        {\n                            reporter.Error(\"Invalid input\");\n                            app.ShowHelp();\n                            return 2;\n                        }\n\n                        _connectionString = connectionStringArg.Value;\n                        _schemaName = schemaNameArg.Value;\n                        _tableName = tableNameArg.Value;\n\n                        return CreateTableAndIndexes(reporter);\n                    });\n                });\n\n                // Show help information if no subcommand/option was specified.\n                app.OnExecute(() =>\n                {\n                    app.ShowHelp();\n                    return 2;\n                });\n\n                return app.Execute(args);\n            }\n            catch (Exception exception)\n            {\n                CreateReporter(verbose: false).Error($\"An error occurred. {exception.Message}\");\n                return 1;\n            }\n        }\n\n        private IReporter CreateReporter(bool verbose)\n            => new ConsoleReporter(_console, verbose, quiet: false);\n        private int CreateTableAndIndexes(IReporter reporter)\n        {\n            ValidateConnectionString();\n\n            using (var connection = new SqlConnection(_connectionString))\n            {\n                connection.Open();\n\n                var sqlQueries = new SqlQueries(_schemaName, _tableName);\n                var command = new SqlCommand(sqlQueries.TableInfo, connection);\n\n                using (var reader = command.ExecuteReader(CommandBehavior.SingleRow))\n                {\n                    if (reader.Read())\n                    {\n                        reporter.Warn(\n                            $\"Table with schema '{_schemaName}' and name '{_tableName}' already exists. \" +\n                            \"Provide a different table name and try again.\");\n                        return 1;\n                    }\n                }\n\n                using (var transaction = connection.BeginTransaction())\n                {\n                    try\n                    {\n                        command = new SqlCommand(sqlQueries.CreateTable, connection, transaction);\n\n                        reporter.Verbose($\"Executing {command.CommandText}\");\n                        command.ExecuteNonQuery();\n\n                        command = new SqlCommand(\n                            sqlQueries.CreateNonClusteredIndexOnExpirationTime,\n                            connection,\n                            transaction);\n\n                        reporter.Verbose($\"Executing {command.CommandText}\");\n                        command.ExecuteNonQuery();\n\n                        transaction.Commit();\n\n                        reporter.Output(\"Table and index were created successfully.\");\n                    }\n                    catch (Exception ex)\n                    {\n                        reporter.Error(\n                            $\"An error occurred while trying to create the table and index. {ex.Message}\");\n                        transaction.Rollback();\n\n                        return 1;\n                    }\n                }\n            }\n\n            return 0;\n        }\n\n        private void ValidateConnectionString()\n        {\n            try\n            {\n                new SqlConnectionStringBuilder(_connectionString);\n            }\n            catch (Exception ex)\n            {\n                throw new ArgumentException(\n                    $\"Invalid SQL Server connection string '{_connectionString}'. {ex.Message}\", ex);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-sql-cache/README.md",
    "content": "dotnet-sql-cache\n================\n\n`dotnet-sql-cache` is a command line tool that creates table and indexes in Microsoft SQL Server database to be used for distributed caching\n\n### How To Use\n\nRun `dotnet sql-cache --help` for more information about usage.\n"
  },
  {
    "path": "src/dotnet-sql-cache/SqlQueries.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\n\nnamespace Microsoft.Extensions.Caching.SqlConfig.Tools\n{\n    internal class SqlQueries\n    {\n        private const string CreateTableFormat = \"CREATE TABLE {0}(\" +\n            // Maximum size of primary key column is 900 bytes (898 bytes from key + 2 additional bytes used by the\n            // Sql Server). In the case where the key is greater than 898 bytes, then it gets truncated.\n            // - Add collation to the key column to make it case-sensitive\n            \"Id nvarchar(449) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, \" +\n            \"Value varbinary(MAX) NOT NULL, \" +\n            \"ExpiresAtTime datetimeoffset NOT NULL, \" +\n            \"SlidingExpirationInSeconds bigint NULL,\" +\n            \"AbsoluteExpiration datetimeoffset NULL, \" +\n            \"PRIMARY KEY (Id))\";\n\n        private const string CreateNonClusteredIndexOnExpirationTimeFormat\n            = \"CREATE NONCLUSTERED INDEX Index_ExpiresAtTime ON {0}(ExpiresAtTime)\";\n\n        private const string TableInfoFormat =\n             \"SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE \" +\n             \"FROM INFORMATION_SCHEMA.TABLES \" +\n             \"WHERE TABLE_SCHEMA = '{0}' \" +\n             \"AND TABLE_NAME = '{1}'\";\n\n        public SqlQueries(string schemaName, string tableName)\n        {\n            if (string.IsNullOrEmpty(schemaName))\n            {\n                throw new ArgumentException(\"Schema name cannot be empty or null\");\n            }\n            if (string.IsNullOrEmpty(tableName))\n            {\n                throw new ArgumentException(\"Table name cannot be empty or null\");\n            }\n\n            var tableNameWithSchema = string.Format(\n                \"{0}.{1}\", DelimitIdentifier(schemaName), DelimitIdentifier(tableName));\n            CreateTable = string.Format(CreateTableFormat, tableNameWithSchema);\n            CreateNonClusteredIndexOnExpirationTime = string.Format(\n                CreateNonClusteredIndexOnExpirationTimeFormat,\n                tableNameWithSchema);\n            TableInfo = string.Format(TableInfoFormat, EscapeLiteral(schemaName), EscapeLiteral(tableName));\n        }\n\n        public string CreateTable { get; }\n\n        public string CreateNonClusteredIndexOnExpirationTime { get; }\n\n        public string TableInfo { get; }\n\n        // From EF's SqlServerQuerySqlGenerator\n        private string DelimitIdentifier(string identifier)\n        {\n            return \"[\" + identifier.Replace(\"]\", \"]]\") + \"]\";\n        }\n\n        private string EscapeLiteral(string literal)\n        {\n            return literal.Replace(\"'\", \"''\");\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-sql-cache/dotnet-sql-cache.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n    <OutputType>exe</OutputType>\n    <Description>Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching.</Description>\n    <PackageTags>cache;distributedcache;sqlserver</PackageTags>\n    <PackAsTool>true</PackAsTool>\n    <!-- This is a requirement for Microsoft tool packages only. -->\n    <PackAsToolShimRuntimeIdentifiers>win-x64;win-x86</PackAsToolShimRuntimeIdentifiers>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Compile Include=\"..\\..\\shared\\**\\*.cs\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.Extensions.CommandLineUtils.Sources\" PrivateAssets=\"All\" Version=\"$(MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion)\" />\n    <PackageReference Include=\"System.Data.SqlClient\" Version=\"$(SystemDataSqlClientPackageVersion)\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <!-- These files should be signed by corefx -->\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)runtimes/win-arm64/native/sni.dll\" PackagePath=\"tools/$(TargetFramework)/any/runtimes/win-arm64/native/sni.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)runtimes/win-x64/native/sni.dll\" PackagePath=\"tools/$(TargetFramework)/any/runtimes/win-x64/native/sni.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)runtimes/win-x86/native/sni.dll\" PackagePath=\"tools/$(TargetFramework)/any/runtimes/win-x86/native/sni.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)System.Data.SqlClient.dll\" PackagePath=\"tools/$(TargetFramework)/any/System.Data.SqlClient.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)System.Security.Permissions.dll\" PackagePath=\"tools/$(TargetFramework)/any/System.Security.Permissions.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll\" PackagePath=\"tools/$(TargetFramework)/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll\" PackagePath=\"tools/$(TargetFramework)/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)System.Runtime.CompilerServices.Unsafe.dll\" PackagePath=\"tools/$(TargetFramework)/any/System.Runtime.CompilerServices.Unsafe.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)System.Text.Encoding.CodePages.dll\" PackagePath=\"tools/$(TargetFramework)/any/System.Text.Encoding.CodePages.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll\" PackagePath=\"tools/$(TargetFramework)/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/dotnet-user-secrets/CommandLineOptions.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Reflection;\nusing Microsoft.Extensions.CommandLineUtils;\nusing Microsoft.Extensions.SecretManager.Tools.Internal;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.Extensions.SecretManager.Tools\n{\n    public class CommandLineOptions\n    {\n        public ICommand Command { get; set; }\n        public string Configuration { get; private set; }\n        public string Id { get; private set; }\n        public bool IsHelp { get; private set; }\n        public bool IsVerbose { get; private set; }\n        public string Project { get; private set; }\n\n        public static CommandLineOptions Parse(string[] args, IConsole console)\n        {\n            var app = new CommandLineApplication()\n            {\n                Out = console.Out,\n                Error = console.Error,\n                Name = \"dotnet user-secrets\",\n                FullName = \"User Secrets Manager\",\n                Description = \"Manages user secrets\"\n            };\n\n            app.HelpOption();\n            app.VersionOptionFromAssemblyAttributes(typeof(Program).GetTypeInfo().Assembly);\n\n            var optionVerbose = app.VerboseOption();\n\n            var optionProject = app.Option(\"-p|--project <PROJECT>\", \"Path to project. Defaults to searching the current directory.\",\n                CommandOptionType.SingleValue, inherited: true);\n\n            var optionConfig = app.Option(\"-c|--configuration <CONFIGURATION>\", $\"The project configuration to use. Defaults to 'Debug'.\",\n                CommandOptionType.SingleValue, inherited: true);\n\n            // the escape hatch if project evaluation fails, or if users want to alter a secret store other than the one\n            // in the current project\n            var optionId = app.Option(\"--id\", \"The user secret ID to use.\",\n                CommandOptionType.SingleValue, inherited: true);\n\n            var options = new CommandLineOptions();\n\n            app.Command(\"set\", c => SetCommand.Configure(c, options, console));\n            app.Command(\"remove\", c => RemoveCommand.Configure(c, options));\n            app.Command(\"list\", c => ListCommand.Configure(c, options));\n            app.Command(\"clear\", c => ClearCommand.Configure(c, options));\n            app.Command(\"init\", c => InitCommandFactory.Configure(c, options));\n\n            // Show help information if no subcommand/option was specified.\n            app.OnExecute(() => app.ShowHelp());\n\n            if (app.Execute(args) != 0)\n            {\n                // when command line parsing error in subcommand\n                return null;\n            }\n\n            options.Configuration = optionConfig.Value();\n            options.Id = optionId.Value();\n            options.IsHelp = app.IsShowingInformation;\n            options.IsVerbose = optionVerbose.HasValue();\n            options.Project = optionProject.Value();\n\n            return options;\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-user-secrets/Internal/ClearCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.Extensions.CommandLineUtils;\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Internal\n{\n    internal class ClearCommand : ICommand\n    {\n        public static void Configure(CommandLineApplication command, CommandLineOptions options)\n        {\n            command.Description = \"Deletes all the application secrets\";\n            command.HelpOption();\n\n            command.OnExecute(() =>\n            {\n                options.Command = new ClearCommand();\n            });\n        }\n\n        public void Execute(CommandContext context)\n        {\n            context.SecretStore.Clear();\n            context.SecretStore.Save();\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-user-secrets/Internal/CommandContext.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Internal\n{\n    public class CommandContext\n    {\n        public CommandContext(\n            SecretsStore store,\n            IReporter reporter,\n            IConsole console)\n        {\n            SecretStore = store;\n            Reporter = reporter;\n            Console = console;\n        }\n\n        public IConsole Console { get; }\n        public IReporter Reporter { get; }\n        public SecretsStore SecretStore { get; }\n    }\n}"
  },
  {
    "path": "src/dotnet-user-secrets/Internal/ICommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Internal\n{\n    public interface ICommand\n    {\n        void Execute(CommandContext context);\n    }\n}"
  },
  {
    "path": "src/dotnet-user-secrets/Internal/InitCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing System.Xml.Linq;\nusing System.Xml.XPath;\nusing Microsoft.Extensions.CommandLineUtils;\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Internal\n{\n    // Workaround used to handle the fact that the options have not been parsed at configuration time\n    public class InitCommandFactory : ICommand\n    {\n        public CommandLineOptions Options { get; }\n\n        internal static void Configure(CommandLineApplication command, CommandLineOptions options)\n        {\n            command.Description = \"Set a user secrets ID to enable secret storage\";\n            command.HelpOption();\n\n            command.OnExecute(() =>\n            {\n                options.Command = new InitCommandFactory(options);\n            });\n        }\n\n        public InitCommandFactory(CommandLineOptions options)\n        {\n            Options = options;\n        }\n\n        public void Execute(CommandContext context)\n        {\n            new InitCommand(Options.Id, Options.Project).Execute(context);\n        }\n\n        public void Execute(CommandContext context, string workingDirectory)\n        {\n            new InitCommand(Options.Id, Options.Project).Execute(context, workingDirectory);\n        }\n    }\n\n    public class InitCommand : ICommand\n    {\n        public string OverrideId { get; }\n        public string ProjectPath { get; }\n        public string WorkingDirectory { get; private set; } = Directory.GetCurrentDirectory();\n\n        public InitCommand(string id, string project)\n        {\n            OverrideId = id;\n            ProjectPath = project;\n        }\n\n        public void Execute(CommandContext context, string workingDirectory)\n        {\n            WorkingDirectory = workingDirectory;\n            Execute(context);\n        }\n\n        public void Execute(CommandContext context)\n        {\n            var projectPath = ResolveProjectPath(ProjectPath, WorkingDirectory);\n\n            // Load the project file as XML\n            var projectDocument = XDocument.Load(projectPath);\n\n            // Accept the `--id` CLI option to the main app\n            string newSecretsId = string.IsNullOrWhiteSpace(OverrideId)\n                ? Guid.NewGuid().ToString()\n                : OverrideId;\n\n            // Confirm secret ID does not contain invalid characters\n            if (Path.GetInvalidPathChars().Any(invalidChar => newSecretsId.Contains(invalidChar)))\n            {\n                throw new ArgumentException(Resources.FormatError_InvalidSecretsId(newSecretsId));\n            }\n\n            var existingUserSecretsId = projectDocument.XPathSelectElements(\"//UserSecretsId\").FirstOrDefault();\n\n            // Check if a UserSecretsId is already set\n            if (existingUserSecretsId != default)\n            {\n                // Only set the UserSecretsId if the user specified an explicit value\n                if (string.IsNullOrWhiteSpace(OverrideId))\n                {\n                    context.Reporter.Output(Resources.FormatMessage_ProjectAlreadyInitialized(projectPath));\n                    return;\n                }\n\n                existingUserSecretsId.SetValue(newSecretsId);\n            }\n            else\n            {\n                // Find the first non-conditional PropertyGroup\n                var propertyGroup = projectDocument.Root.DescendantNodes()\n                    .FirstOrDefault(node => node is XElement el\n                        && el.Name == \"PropertyGroup\"\n                        && el.Attributes().All(attr =>\n                            attr.Name != \"Condition\")) as XElement;\n\n                // No valid property group, create a new one\n                if (propertyGroup == null)\n                {\n                    propertyGroup = new XElement(\"PropertyGroup\");\n                    projectDocument.Root.AddFirst(propertyGroup);\n                }\n\n                // Add UserSecretsId element\n                propertyGroup.Add(new XElement(\"UserSecretsId\", newSecretsId));\n            }\n\n            projectDocument.Save(projectPath);\n\n            context.Reporter.Output(Resources.FormatMessage_SetUserSecretsIdForProject(newSecretsId, projectPath));\n        }\n\n        private static string ResolveProjectPath(string name, string path)\n        {\n            var finder = new MsBuildProjectFinder(path);\n            return finder.FindMsBuildProject(name);\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-user-secrets/Internal/ListCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.Extensions.CommandLineUtils;\nusing Newtonsoft.Json;\nusing Newtonsoft.Json.Linq;\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Internal\n{\n    internal class ListCommand : ICommand\n    {\n        private readonly bool _jsonOutput;\n\n        public static void Configure(CommandLineApplication command, CommandLineOptions options)\n        {\n            command.Description = \"Lists all the application secrets\";\n            command.HelpOption();\n\n            var optJson = command.Option(\"--json\", \"Use json output. JSON is wrapped by '//BEGIN' and '//END'\",\n                CommandOptionType.NoValue);\n\n            command.OnExecute(() =>\n            {\n                options.Command = new ListCommand(optJson.HasValue());\n            });\n        }\n\n        public ListCommand(bool jsonOutput)\n        {\n            _jsonOutput = jsonOutput;\n        }\n\n        public void Execute(CommandContext context)\n        {\n            if (_jsonOutput)\n            {\n                ReportJson(context);\n                return;\n            }\n\n            if (context.SecretStore.Count == 0)\n            {\n                context.Reporter.Output(Resources.Error_No_Secrets_Found);\n            }\n            else\n            {\n                foreach (var secret in context.SecretStore.AsEnumerable())\n                {\n                    context.Reporter.Output(Resources.FormatMessage_Secret_Value_Format(secret.Key, secret.Value));\n                }\n            }\n        }\n\n        private void ReportJson(CommandContext context)\n        {\n            var jObject = new JObject();\n            foreach(var item in context.SecretStore.AsEnumerable())\n            {\n                jObject[item.Key] = item.Value;\n            }\n\n            context.Reporter.Output(\"//BEGIN\");\n            context.Reporter.Output(jObject.ToString(Formatting.Indented));\n            context.Reporter.Output(\"//END\");\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-user-secrets/Internal/MsBuildProjectFinder.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Internal\n{\n    internal class MsBuildProjectFinder\n    {\n        private readonly string _directory;\n\n        public MsBuildProjectFinder(string directory)\n        {\n            Ensure.NotNullOrEmpty(directory, nameof(directory));\n\n            _directory = directory;\n        }\n\n        public string FindMsBuildProject(string project)\n        {\n            var projectPath = project ?? _directory;\n\n            if (!Path.IsPathRooted(projectPath))\n            {\n                projectPath = Path.Combine(_directory, projectPath);\n            }\n\n            if (Directory.Exists(projectPath))\n            {\n                var projects = Directory.EnumerateFileSystemEntries(projectPath, \"*.*proj\", SearchOption.TopDirectoryOnly)\n                    .Where(f => !\".xproj\".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase))\n                    .ToList();\n\n                if (projects.Count > 1)\n                {\n                    throw new FileNotFoundException(Resources.FormatError_MultipleProjectsFound(projectPath));\n                }\n\n                if (projects.Count == 0)\n                {\n                    throw new FileNotFoundException(Resources.FormatError_NoProjectsFound(projectPath));\n                }\n\n                return projects[0];\n            }\n\n            if (!File.Exists(projectPath))\n            {\n                throw new FileNotFoundException(Resources.FormatError_ProjectPath_NotFound(projectPath));\n            }\n\n            return projectPath;\n        }\n    }\n}"
  },
  {
    "path": "src/dotnet-user-secrets/Internal/ProjectIdResolver.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing Microsoft.Extensions.CommandLineUtils;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Internal\n{\n    public class ProjectIdResolver\n    {\n        private const string DefaultConfig = \"Debug\";\n        private readonly IReporter _reporter;\n        private readonly string _targetsFile;\n        private readonly string _workingDirectory;\n\n        public ProjectIdResolver(IReporter reporter, string workingDirectory)\n        {\n            _workingDirectory = workingDirectory;\n            _reporter = reporter;\n            _targetsFile = FindTargetsFile();\n        }\n\n        public string Resolve(string project, string configuration)\n        {\n            var finder = new MsBuildProjectFinder(_workingDirectory);\n            var projectFile = finder.FindMsBuildProject(project);\n\n            _reporter.Verbose(Resources.FormatMessage_Project_File_Path(projectFile));\n\n            configuration = !string.IsNullOrEmpty(configuration)\n                ? configuration\n                : DefaultConfig;\n\n            var outputFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());\n            try\n            {\n                var args = new[]\n                {\n                    \"msbuild\",\n                    projectFile,\n                    \"/nologo\",\n                    \"/t:_ExtractUserSecretsMetadata\", // defined in SecretManager.targets\n                    \"/p:_UserSecretsMetadataFile=\" + outputFile,\n                    \"/p:Configuration=\" + configuration,\n                    \"/p:CustomAfterMicrosoftCommonTargets=\" + _targetsFile,\n                    \"/p:CustomAfterMicrosoftCommonCrossTargetingTargets=\" + _targetsFile,\n                };\n                var psi = new ProcessStartInfo\n                {\n                    FileName = DotNetMuxer.MuxerPathOrDefault(),\n                    Arguments = ArgumentEscaper.EscapeAndConcatenate(args),\n                    RedirectStandardOutput = true,\n                    RedirectStandardError = true\n                };\n\n#if DEBUG\n                _reporter.Verbose($\"Invoking '{psi.FileName} {psi.Arguments}'\");\n#endif\n\n                var process = Process.Start(psi);\n                process.WaitForExit();\n\n                if (process.ExitCode != 0)\n                {\n                    _reporter.Verbose(process.StandardOutput.ReadToEnd());\n                    _reporter.Verbose(process.StandardError.ReadToEnd());\n                    throw new InvalidOperationException(Resources.FormatError_ProjectFailedToLoad(projectFile));\n                }\n\n                var id = File.ReadAllText(outputFile)?.Trim();\n                if (string.IsNullOrEmpty(id))\n                {\n                    throw new InvalidOperationException(Resources.FormatError_ProjectMissingId(projectFile));\n                }\n                return id;\n\n            }\n            finally\n            {\n                TryDelete(outputFile);\n            }\n        }\n\n        private string FindTargetsFile()\n        {\n            var assemblyDir = Path.GetDirectoryName(typeof(ProjectIdResolver).Assembly.Location);\n            var searchPaths = new[]\n            {\n                Path.Combine(AppContext.BaseDirectory, \"assets\"),\n                Path.Combine(assemblyDir, \"assets\"),\n                AppContext.BaseDirectory,\n                assemblyDir,\n            };\n\n            var targetPath = searchPaths.Select(p => Path.Combine(p, \"SecretManager.targets\")).FirstOrDefault(File.Exists);\n            if (targetPath == null)\n            {\n                _reporter.Error(\"Fatal error: could not find SecretManager.targets\");\n                return null;\n            }\n            return targetPath;\n        }\n\n        private static void TryDelete(string file)\n        {\n            try\n            {\n                if (File.Exists(file))\n                {\n                    File.Delete(file);\n                }\n            }\n            catch\n            {\n                // whatever\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-user-secrets/Internal/ReadableJsonConfigurationSource.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing Microsoft.Extensions.Configuration.Json;\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Internal\n{\n    public class ReadableJsonConfigurationProvider : JsonConfigurationProvider\n    {\n        public ReadableJsonConfigurationProvider()\n            : base(new JsonConfigurationSource())\n        {\n        }\n\n        public IDictionary<string, string> CurrentData => Data;\n    }\n}"
  },
  {
    "path": "src/dotnet-user-secrets/Internal/RemoveCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.Extensions.CommandLineUtils;\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Internal\n{\n    internal class RemoveCommand : ICommand\n    {\n        private readonly string _keyName;\n\n        public static void Configure(CommandLineApplication command, CommandLineOptions options)\n        {\n            command.Description = \"Removes the specified user secret\";\n            command.HelpOption();\n\n            var keyArg = command.Argument(\"[name]\", \"Name of the secret\");\n            command.OnExecute(() =>\n            {\n                if (keyArg.Value == null)\n                {\n                    throw new CommandParsingException(command, Resources.FormatError_MissingArgument(\"name\"));\n                }\n\n                options.Command = new RemoveCommand(keyArg.Value);\n            });\n        }\n\n\n        public RemoveCommand(string keyName)\n        {\n            _keyName = keyName;\n        }\n\n        public void Execute(CommandContext context)\n        {\n            if (!context.SecretStore.ContainsKey(_keyName))\n            {\n                context.Reporter.Warn(Resources.FormatError_Missing_Secret(_keyName));\n            }\n            else\n            {\n                context.SecretStore.Remove(_keyName);\n                context.SecretStore.Save();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-user-secrets/Internal/SecretsStore.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.Configuration.UserSecrets;\nusing Microsoft.Extensions.Tools.Internal;\nusing Newtonsoft.Json.Linq;\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Internal\n{\n    public class SecretsStore\n    {\n        private readonly string _secretsFilePath;\n        private IDictionary<string, string> _secrets;\n\n        public SecretsStore(string userSecretsId, IReporter reporter)\n        {\n            Ensure.NotNull(userSecretsId, nameof(userSecretsId));\n\n            _secretsFilePath = PathHelper.GetSecretsPathFromSecretsId(userSecretsId);\n\n            // workaround bug in configuration\n            var secretDir = Path.GetDirectoryName(_secretsFilePath);\n            Directory.CreateDirectory(secretDir);\n\n            reporter.Verbose(Resources.FormatMessage_Secret_File_Path(_secretsFilePath));\n            _secrets = Load(userSecretsId);\n        }\n\n        public string this[string key]\n        {\n            get\n            {\n                return _secrets[key];\n            }\n        }\n\n        public int Count => _secrets.Count;\n\n        public bool ContainsKey(string key) => _secrets.ContainsKey(key);\n\n        public IEnumerable<KeyValuePair<string, string>> AsEnumerable() => _secrets;\n\n        public void Clear() => _secrets.Clear();\n\n        public void Set(string key, string value) => _secrets[key] = value;\n\n        public void Remove(string key)\n        {\n            if (_secrets.ContainsKey(key))\n            {\n                _secrets.Remove(key);\n            }\n        }\n\n        public virtual void Save()\n        {\n            Directory.CreateDirectory(Path.GetDirectoryName(_secretsFilePath));\n\n            var contents = new JObject();\n            if (_secrets != null)\n            {\n                foreach (var secret in _secrets.AsEnumerable())\n                {\n                    contents[secret.Key] = secret.Value;\n                }\n            }\n\n            File.WriteAllText(_secretsFilePath, contents.ToString(), Encoding.UTF8);\n        }\n\n        protected virtual IDictionary<string, string> Load(string userSecretsId)\n        {\n            return new ConfigurationBuilder()\n                .AddJsonFile(_secretsFilePath, optional: true)\n                .Build()\n                .AsEnumerable()\n                .Where(i => i.Value != null)\n                .ToDictionary(i => i.Key, i => i.Value, StringComparer.OrdinalIgnoreCase);\n        }\n    }\n}"
  },
  {
    "path": "src/dotnet-user-secrets/Internal/SetCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.IO;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing Microsoft.Extensions.CommandLineUtils;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Internal\n{\n    internal class SetCommand\n    {\n        public static void Configure(CommandLineApplication command, CommandLineOptions options, IConsole console)\n        {\n            command.Description = \"Sets the user secret to the specified value\";\n            command.ExtendedHelpText = @\"\nAdditional Info:\n  This command will also handle piped input. Piped input is expected to be a valid JSON format.\n\nExamples:\n  dotnet user-secrets set ConnStr \"\"User ID=bob;Password=***\"\"\n\";\n\n            var catCmd = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)\n                ? @\"type .\\secrets.json\"\n                : \"cat ./secrets.json\";\n\n            command.ExtendedHelpText += $@\"  {catCmd} | dotnet user-secrets set\";\n\n            command.HelpOption();\n\n            var nameArg = command.Argument(\"[name]\", \"Name of the secret\");\n            var valueArg = command.Argument(\"[value]\", \"Value of the secret\");\n\n            command.OnExecute(() =>\n            {\n                if (console.IsInputRedirected && nameArg.Value == null)\n                {\n                    options.Command = new FromStdInStrategy();\n                }\n                else\n                {\n                    if (string.IsNullOrEmpty(nameArg.Value))\n                    {\n                        throw new CommandParsingException(command, Resources.FormatError_MissingArgument(\"name\"));\n                    }\n\n                    if (valueArg.Value == null)\n                    {\n                        throw new CommandParsingException(command, Resources.FormatError_MissingArgument(\"value\"));\n                    }\n\n                    options.Command = new ForOneValueStrategy(nameArg.Value, valueArg.Value);\n                }\n            });\n        }\n\n        public class FromStdInStrategy : ICommand\n        {\n            public void Execute(CommandContext context)\n            {\n                // parses stdin with the same parser that Microsoft.Extensions.Configuration.Json would use\n                var provider = new ReadableJsonConfigurationProvider();\n                using (var stream = new MemoryStream())\n                {\n                    using (var writer = new StreamWriter(stream, Encoding.Unicode, 1024, true))\n                    {\n                        writer.Write(context.Console.In.ReadToEnd()); // TODO buffer?\n                    }\n\n                    stream.Seek(0, SeekOrigin.Begin);\n                    provider.Load(stream);\n                }\n\n                foreach (var k in provider.CurrentData)\n                {\n                    context.SecretStore.Set(k.Key, k.Value);\n                }\n\n                context.Reporter.Output(Resources.FormatMessage_Saved_Secrets(provider.CurrentData.Count));\n\n                context.SecretStore.Save();\n            }\n        }\n\n        public class ForOneValueStrategy : ICommand\n        {\n            private readonly string _keyName;\n            private readonly string _keyValue;\n\n            public ForOneValueStrategy(string keyName, string keyValue)\n            {\n                _keyName = keyName;\n                _keyValue = keyValue;\n            }\n\n            public void Execute(CommandContext context)\n            {\n                context.SecretStore.Set(_keyName, _keyValue);\n                context.SecretStore.Save();\n                context.Reporter.Output(Resources.FormatMessage_Saved_Secret(_keyName, _keyValue));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-user-secrets/Program.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing Microsoft.Extensions.CommandLineUtils;\nusing Microsoft.Extensions.SecretManager.Tools.Internal;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.Extensions.SecretManager.Tools\n{\n    public class Program\n    {\n        private readonly IConsole _console;\n        private readonly string _workingDirectory;\n\n        public static int Main(string[] args)\n        {\n            DebugHelper.HandleDebugSwitch(ref args);\n\n            int rc;\n            new Program(PhysicalConsole.Singleton, Directory.GetCurrentDirectory()).TryRun(args, out rc);\n            return rc;\n        }\n\n        public Program(IConsole console, string workingDirectory)\n        {\n            _console = console;\n            _workingDirectory = workingDirectory;\n        }\n\n        public bool TryRun(string[] args, out int returnCode)\n        {\n            try\n            {\n                returnCode = RunInternal(args);\n                return true;\n            }\n            catch (Exception exception)\n            {\n                var reporter = CreateReporter(verbose: true);\n                reporter.Verbose(exception.ToString());\n                reporter.Error(Resources.FormatError_Command_Failed(exception.Message));\n                returnCode = 1;\n                return false;\n            }\n        }\n\n        internal int RunInternal(params string[] args)\n        {\n            CommandLineOptions options;\n            try\n            {\n                options = CommandLineOptions.Parse(args, _console);\n            }\n            catch (CommandParsingException ex)\n            {\n                CreateReporter(verbose: false).Error(ex.Message);\n                return 1;\n            }\n\n            if (options == null)\n            {\n                return 1;\n            }\n\n            if (options.IsHelp)\n            {\n                return 2;\n            }\n\n            var reporter = CreateReporter(options.IsVerbose);\n\n            if (options.Command is InitCommandFactory initCmd)\n            {\n                initCmd.Execute(new CommandContext(null, reporter, _console), _workingDirectory);\n                return 0;\n            }\n\n            string userSecretsId;\n            try\n            {\n                userSecretsId = ResolveId(options, reporter);\n            }\n            catch (Exception ex) when (ex is InvalidOperationException || ex is FileNotFoundException)\n            {\n                reporter.Error(ex.Message);\n                return 1;\n            }\n\n            var store = new SecretsStore(userSecretsId, reporter);\n            var context = new Internal.CommandContext(store, reporter, _console);\n            options.Command.Execute(context);\n            return 0;\n        }\n\n        private IReporter CreateReporter(bool verbose)\n            => new ConsoleReporter(_console, verbose, quiet: false);\n\n        internal string ResolveId(CommandLineOptions options, IReporter reporter)\n        {\n            if (!string.IsNullOrEmpty(options.Id))\n            {\n                return options.Id;\n            }\n\n            var resolver = new ProjectIdResolver(reporter, _workingDirectory);\n            return resolver.Resolve(options.Project, options.Configuration);\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-user-secrets/Properties/AssemblyInfo.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Runtime.CompilerServices;\n\n[assembly: InternalsVisibleTo(\"Microsoft.Extensions.SecretManager.Tools.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb\")]\n"
  },
  {
    "path": "src/dotnet-user-secrets/Properties/Resources.Designer.cs",
    "content": "// <auto-generated />\nnamespace Microsoft.Extensions.SecretManager.Tools\n{\n    using System.Globalization;\n    using System.Reflection;\n    using System.Resources;\n\n    internal static class Resources\n    {\n        private static readonly ResourceManager _resourceManager\n            = new ResourceManager(\"Microsoft.Extensions.SecretManager.Tools.Resources\", typeof(Resources).GetTypeInfo().Assembly);\n\n        /// <summary>\n        /// Command failed : {message}\n        /// </summary>\n        internal static string Error_Command_Failed\n        {\n            get => GetString(\"Error_Command_Failed\");\n        }\n\n        /// <summary>\n        /// Command failed : {message}\n        /// </summary>\n        internal static string FormatError_Command_Failed(object message)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Error_Command_Failed\", \"message\"), message);\n\n        /// <summary>\n        /// Missing parameter value for '{name}'.\n        /// Use the '--help' flag to see info.\n        /// </summary>\n        internal static string Error_MissingArgument\n        {\n            get => GetString(\"Error_MissingArgument\");\n        }\n\n        /// <summary>\n        /// Missing parameter value for '{name}'.\n        /// Use the '--help' flag to see info.\n        /// </summary>\n        internal static string FormatError_MissingArgument(object name)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Error_MissingArgument\", \"name\"), name);\n\n        /// <summary>\n        /// Cannot find '{key}' in the secret store.\n        /// </summary>\n        internal static string Error_Missing_Secret\n        {\n            get => GetString(\"Error_Missing_Secret\");\n        }\n\n        /// <summary>\n        /// Cannot find '{key}' in the secret store.\n        /// </summary>\n        internal static string FormatError_Missing_Secret(object key)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Error_Missing_Secret\", \"key\"), key);\n\n        /// <summary>\n        /// Multiple MSBuild project files found in '{projectPath}'. Specify which to use with the --project option.\n        /// </summary>\n        internal static string Error_MultipleProjectsFound\n        {\n            get => GetString(\"Error_MultipleProjectsFound\");\n        }\n\n        /// <summary>\n        /// Multiple MSBuild project files found in '{projectPath}'. Specify which to use with the --project option.\n        /// </summary>\n        internal static string FormatError_MultipleProjectsFound(object projectPath)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Error_MultipleProjectsFound\", \"projectPath\"), projectPath);\n\n        /// <summary>\n        /// No secrets configured for this application.\n        /// </summary>\n        internal static string Error_No_Secrets_Found\n        {\n            get => GetString(\"Error_No_Secrets_Found\");\n        }\n\n        /// <summary>\n        /// No secrets configured for this application.\n        /// </summary>\n        internal static string FormatError_No_Secrets_Found()\n            => GetString(\"Error_No_Secrets_Found\");\n\n        /// <summary>\n        /// Could not find a MSBuild project file in '{projectPath}'. Specify which project to use with the --project option.\n        /// </summary>\n        internal static string Error_NoProjectsFound\n        {\n            get => GetString(\"Error_NoProjectsFound\");\n        }\n\n        /// <summary>\n        /// Could not find a MSBuild project file in '{projectPath}'. Specify which project to use with the --project option.\n        /// </summary>\n        internal static string FormatError_NoProjectsFound(object projectPath)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Error_NoProjectsFound\", \"projectPath\"), projectPath);\n\n        /// <summary>\n        /// 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.\n        /// </summary>\n        internal static string Error_ProjectMissingId\n        {\n            get => GetString(\"Error_ProjectMissingId\");\n        }\n\n        /// <summary>\n        /// 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.\n        /// </summary>\n        internal static string FormatError_ProjectMissingId(object project)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Error_ProjectMissingId\", \"project\"), project);\n\n        /// <summary>\n        /// The project file '{path}' does not exist.\n        /// </summary>\n        internal static string Error_ProjectPath_NotFound\n        {\n            get => GetString(\"Error_ProjectPath_NotFound\");\n        }\n\n        /// <summary>\n        /// The project file '{path}' does not exist.\n        /// </summary>\n        internal static string FormatError_ProjectPath_NotFound(object path)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Error_ProjectPath_NotFound\", \"path\"), path);\n\n        /// <summary>\n        /// Could not load the MSBuild project '{project}'.\n        /// </summary>\n        internal static string Error_ProjectFailedToLoad\n        {\n            get => GetString(\"Error_ProjectFailedToLoad\");\n        }\n\n        /// <summary>\n        /// Could not load the MSBuild project '{project}'.\n        /// </summary>\n        internal static string FormatError_ProjectFailedToLoad(object project)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Error_ProjectFailedToLoad\", \"project\"), project);\n\n        /// <summary>\n        /// Project file path {project}.\n        /// </summary>\n        internal static string Message_Project_File_Path\n        {\n            get => GetString(\"Message_Project_File_Path\");\n        }\n\n        /// <summary>\n        /// Project file path {project}.\n        /// </summary>\n        internal static string FormatMessage_Project_File_Path(object project)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Message_Project_File_Path\", \"project\"), project);\n\n        /// <summary>\n        /// Successfully saved {key} = {value} to the secret store.\n        /// </summary>\n        internal static string Message_Saved_Secret\n        {\n            get => GetString(\"Message_Saved_Secret\");\n        }\n\n        /// <summary>\n        /// Successfully saved {key} = {value} to the secret store.\n        /// </summary>\n        internal static string FormatMessage_Saved_Secret(object key, object value)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Message_Saved_Secret\", \"key\", \"value\"), key, value);\n\n        /// <summary>\n        /// Successfully saved {number} secrets to the secret store.\n        /// </summary>\n        internal static string Message_Saved_Secrets\n        {\n            get => GetString(\"Message_Saved_Secrets\");\n        }\n\n        /// <summary>\n        /// Successfully saved {number} secrets to the secret store.\n        /// </summary>\n        internal static string FormatMessage_Saved_Secrets(object number)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Message_Saved_Secrets\", \"number\"), number);\n\n        /// <summary>\n        /// Secrets file path {secretsFilePath}.\n        /// </summary>\n        internal static string Message_Secret_File_Path\n        {\n            get => GetString(\"Message_Secret_File_Path\");\n        }\n\n        /// <summary>\n        /// Secrets file path {secretsFilePath}.\n        /// </summary>\n        internal static string FormatMessage_Secret_File_Path(object secretsFilePath)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Message_Secret_File_Path\", \"secretsFilePath\"), secretsFilePath);\n\n        /// <summary>\n        /// {key} = {value}\n        /// </summary>\n        internal static string Message_Secret_Value_Format\n        {\n            get => GetString(\"Message_Secret_Value_Format\");\n        }\n\n        /// <summary>\n        /// {key} = {value}\n        /// </summary>\n        internal static string FormatMessage_Secret_Value_Format(object key, object value)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Message_Secret_Value_Format\", \"key\", \"value\"), key, value);\n\n        /// <summary>\n        /// The UserSecretsId '{userSecretsId}' cannot contain any characters that cannot be used in a file path.\n        /// </summary>\n        internal static string Error_InvalidSecretsId\n        {\n            get => GetString(\"Error_InvalidSecretsId\");\n        }\n\n        /// <summary>\n        /// The UserSecretsId '{userSecretsId}' cannot contain any characters that cannot be used in a file path.\n        /// </summary>\n        internal static string FormatError_InvalidSecretsId(object userSecretsId)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Error_InvalidSecretsId\", \"userSecretsId\"), userSecretsId);\n\n        /// <summary>\n        /// The MSBuild project '{project}' has already been initialized with a UserSecretsId.\n        /// </summary>\n        internal static string Message_ProjectAlreadyInitialized\n        {\n            get => GetString(\"Message_ProjectAlreadyInitialized\");\n        }\n\n        /// <summary>\n        /// The MSBuild project '{project}' has already been initialized with a UserSecretsId.\n        /// </summary>\n        internal static string FormatMessage_ProjectAlreadyInitialized(object project)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Message_ProjectAlreadyInitialized\", \"project\"), project);\n\n        /// <summary>\n        /// Set UserSecretsId to '{userSecretsId}' for MSBuild project '{project}'.\n        /// </summary>\n        internal static string Message_SetUserSecretsIdForProject\n        {\n            get => GetString(\"Message_SetUserSecretsIdForProject\");\n        }\n\n        /// <summary>\n        /// Set UserSecretsId to '{userSecretsId}' for MSBuild project '{project}'.\n        /// </summary>\n        internal static string FormatMessage_SetUserSecretsIdForProject(object userSecretsId, object project)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Message_SetUserSecretsIdForProject\", \"userSecretsId\", \"project\"), userSecretsId, project);\n\n        private static string GetString(string name, params string[] formatterNames)\n        {\n            var value = _resourceManager.GetString(name);\n\n            System.Diagnostics.Debug.Assert(value != null);\n\n            if (formatterNames != null)\n            {\n                for (var i = 0; i < formatterNames.Length; i++)\n                {\n                    value = value.Replace(\"{\" + formatterNames[i] + \"}\", \"{\" + i + \"}\");\n                }\n            }\n\n            return value;\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-user-secrets/README.md",
    "content": "dotnet-user-secrets\n===================\n\n`dotnet-user-secrets` is a command line tool for managing the secrets in a user secret store.\n\n### How To Use\n\nRun `dotnet user-secrets --help` for more information about usage.\n"
  },
  {
    "path": "src/dotnet-user-secrets/Resources.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"Error_Command_Failed\" xml:space=\"preserve\">\n    <value>Command failed : {message}</value>\n  </data>\n  <data name=\"Error_MissingArgument\" xml:space=\"preserve\">\n    <value>Missing parameter value for '{name}'.\nUse the '--help' flag to see info.</value>\n  </data>\n  <data name=\"Error_Missing_Secret\" xml:space=\"preserve\">\n    <value>Cannot find '{key}' in the secret store.</value>\n  </data>\n  <data name=\"Error_MultipleProjectsFound\" xml:space=\"preserve\">\n    <value>Multiple MSBuild project files found in '{projectPath}'. Specify which to use with the --project option.</value>\n  </data>\n  <data name=\"Error_No_Secrets_Found\" xml:space=\"preserve\">\n    <value>No secrets configured for this application.</value>\n  </data>\n  <data name=\"Error_NoProjectsFound\" xml:space=\"preserve\">\n    <value>Could not find a MSBuild project file in '{projectPath}'. Specify which project to use with the --project option.</value>\n  </data>\n  <data name=\"Error_ProjectMissingId\" xml:space=\"preserve\">\n    <value>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.</value>\n  </data>\n  <data name=\"Error_ProjectPath_NotFound\" xml:space=\"preserve\">\n    <value>The project file '{path}' does not exist.</value>\n  </data>\n  <data name=\"Error_ProjectFailedToLoad\" xml:space=\"preserve\">\n    <value>Could not load the MSBuild project '{project}'.</value>\n  </data>\n  <data name=\"Message_Project_File_Path\" xml:space=\"preserve\">\n    <value>Project file path {project}.</value>\n  </data>\n  <data name=\"Message_Saved_Secret\" xml:space=\"preserve\">\n    <value>Successfully saved {key} = {value} to the secret store.</value>\n  </data>\n  <data name=\"Message_Saved_Secrets\" xml:space=\"preserve\">\n    <value>Successfully saved {number} secrets to the secret store.</value>\n  </data>\n  <data name=\"Message_Secret_File_Path\" xml:space=\"preserve\">\n    <value>Secrets file path {secretsFilePath}.</value>\n  </data>\n  <data name=\"Message_Secret_Value_Format\" xml:space=\"preserve\">\n    <value>{key} = {value}</value>\n  </data>\n  <data name=\"Error_InvalidSecretsId\" xml:space=\"preserve\">\n    <value>The UserSecretsId '{userSecretsId}' cannot contain any characters that cannot be used in a file path.</value>\n  </data>\n  <data name=\"Message_ProjectAlreadyInitialized\" xml:space=\"preserve\">\n    <value>The MSBuild project '{project}' has already been initialized with a UserSecretsId.</value>\n  </data>\n  <data name=\"Message_SetUserSecretsIdForProject\" xml:space=\"preserve\">\n    <value>Set UserSecretsId to '{userSecretsId}' for MSBuild project '{project}'.</value>\n  </data>\n</root>"
  },
  {
    "path": "src/dotnet-user-secrets/assets/SecretManager.targets",
    "content": "<Project>\n  <Target Name=\"_ExtractUserSecretsMetadata\">\n    <WriteLinesToFile File=\"$(_UserSecretsMetadataFile)\" Lines=\"$(UserSecretsId)\" />\n  </Target>\n</Project>\n"
  },
  {
    "path": "src/dotnet-user-secrets/dotnet-user-secrets.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n    <OutputType>exe</OutputType>\n    <Description>Command line tool to manage user secrets for Microsoft.Extensions.Configuration.</Description>\n    <GenerateUserSecretsAttribute>false</GenerateUserSecretsAttribute>\n    <RootNamespace>Microsoft.Extensions.SecretManager.Tools</RootNamespace>\n    <PackageTags>configuration;secrets;usersecrets</PackageTags>\n    <PackAsTool>true</PackAsTool>\n    <!-- This is a requirement for Microsoft tool packages only. -->\n    <PackAsToolShimRuntimeIdentifiers>win-x64;win-x86</PackAsToolShimRuntimeIdentifiers>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Compile Include=\"..\\..\\shared\\**\\*.cs\" />\n    <None Include=\"assets\\**\\*\" CopyToOutputDirectory=\"PreserveNewest\" CopyToPublishDirectory=\"PreserveNewest\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.Extensions.CommandLineUtils.Sources\" PrivateAssets=\"All\" Version=\"$(MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Configuration.UserSecrets\" Version=\"$(MicrosoftExtensionsConfigurationUserSecretsPackageVersion)\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <!-- 3rd party binary -->\n    <SignedPackageFile Include=\"$(PublishDir)Newtonsoft.Json.dll\" PackagePath=\"tools/$(TargetFramework)/any/Newtonsoft.Json.dll\" Certificate=\"$(AssemblySigning3rdPartyCertName)\" />\n\n    <!-- Exclude files that should already be signed -->\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)Microsoft.Extensions.Configuration.dll\" PackagePath=\"tools/$(TargetFramework)/any/Microsoft.Extensions.Configuration.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)Microsoft.Extensions.Configuration.Abstractions.dll\" PackagePath=\"tools/$(TargetFramework)/any/Microsoft.Extensions.Configuration.Abstractions.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)Microsoft.Extensions.Configuration.FileExtensions.dll\" PackagePath=\"tools/$(TargetFramework)/any/Microsoft.Extensions.Configuration.FileExtensions.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)Microsoft.Extensions.Configuration.Json.dll\" PackagePath=\"tools/$(TargetFramework)/any/Microsoft.Extensions.Configuration.Json.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)Microsoft.Extensions.Configuration.UserSecrets.dll\" PackagePath=\"tools/$(TargetFramework)/any/Microsoft.Extensions.Configuration.UserSecrets.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)Microsoft.Extensions.FileProviders.Abstractions.dll\" PackagePath=\"tools/$(TargetFramework)/any/Microsoft.Extensions.FileProviders.Abstractions.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)Microsoft.Extensions.FileProviders.Physical.dll\" PackagePath=\"tools/$(TargetFramework)/any/Microsoft.Extensions.FileProviders.Physical.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)Microsoft.Extensions.FileSystemGlobbing.dll\" PackagePath=\"tools/$(TargetFramework)/any/Microsoft.Extensions.FileSystemGlobbing.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)Microsoft.Extensions.Primitives.dll\" PackagePath=\"tools/$(TargetFramework)/any/Microsoft.Extensions.Primitives.dll\" />\n    <ExcludePackageFileFromSigning Include=\"$(PublishDir)System.Runtime.CompilerServices.Unsafe.dll\" PackagePath=\"tools/$(TargetFramework)/any/System.Runtime.CompilerServices.Unsafe.dll\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/dotnet-watch/CommandLineOptions.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing Microsoft.DotNet.Watcher.Tools;\nusing Microsoft.Extensions.CommandLineUtils;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.DotNet.Watcher\n{\n    internal class CommandLineOptions\n    {\n        public string Project { get; private set; }\n        public bool IsHelp { get; private set; }\n        public bool IsQuiet { get; private set; }\n        public bool IsVerbose { get; private set; }\n        public IList<string> RemainingArguments { get; private set; }\n        public bool ListFiles { get; private set; }\n\n        public static bool IsPollingEnabled\n        {\n            get\n            {\n                var envVar = Environment.GetEnvironmentVariable(\"DOTNET_USE_POLLING_FILE_WATCHER\");\n                return envVar != null &&\n                    (envVar.Equals(\"1\", StringComparison.OrdinalIgnoreCase) ||\n                     envVar.Equals(\"true\", StringComparison.OrdinalIgnoreCase));\n            }\n        }\n\n        public static CommandLineOptions Parse(string[] args, IConsole console)\n        {\n            Ensure.NotNull(args, nameof(args));\n            Ensure.NotNull(console, nameof(console));\n\n            var app = new CommandLineApplication(throwOnUnexpectedArg: false)\n            {\n                Name = \"dotnet watch\",\n                FullName = \"Microsoft DotNet File Watcher\",\n                Out = console.Out,\n                Error = console.Error,\n                AllowArgumentSeparator = true,\n                ExtendedHelpText = @\"\nEnvironment variables:\n\n  DOTNET_USE_POLLING_FILE_WATCHER\n  When set to '1' or 'true', dotnet-watch will poll the file system for\n  changes. This is required for some file systems, such as network shares,\n  Docker mounted volumes, and other virtual file systems.\n\n  DOTNET_WATCH\n  dotnet-watch sets this variable to '1' on all child processes launched.\n\n  DOTNET_WATCH_ITERATION\n  dotnet-watch sets this variable to '1' and increments by one each time\n  a file is changed and the command is restarted.\n\nRemarks:\n  The special option '--' is used to delimit the end of the options and\n  the beginning of arguments that will be passed to the child dotnet process.\n  Its use is optional. When the special option '--' is not used,\n  dotnet-watch will use the first unrecognized argument as the beginning\n  of all arguments passed into the child dotnet process.\n\n  For example: dotnet watch -- --verbose run\n\n  Even though '--verbose' is an option dotnet-watch supports, the use of '--'\n  indicates that '--verbose' should be treated instead as an argument for\n  dotnet-run.\n\nExamples:\n  dotnet watch run\n  dotnet watch test\n\"\n            };\n\n            app.HelpOption(\"-?|-h|--help\");\n            // TODO multiple shouldn't be too hard to support\n            var optProjects = app.Option(\"-p|--project <PROJECT>\", \"The project to watch\",\n                CommandOptionType.SingleValue);\n\n            var optQuiet = app.Option(\"-q|--quiet\", \"Suppresses all output except warnings and errors\",\n                CommandOptionType.NoValue);\n            var optVerbose = app.VerboseOption();\n\n            var optList = app.Option(\"--list\", \"Lists all discovered files without starting the watcher\",\n                CommandOptionType.NoValue);\n\n            app.VersionOptionFromAssemblyAttributes(typeof(Program).GetTypeInfo().Assembly);\n\n            if (app.Execute(args) != 0)\n            {\n                return null;\n            }\n\n            if (optQuiet.HasValue() && optVerbose.HasValue())\n            {\n                throw new CommandParsingException(app, Resources.Error_QuietAndVerboseSpecified);\n            }\n\n            if (app.RemainingArguments.Count == 0\n                && !app.IsShowingInformation\n                && !optList.HasValue())\n            {\n                app.ShowHelp();\n            }\n\n            return new CommandLineOptions\n            {\n                Project = optProjects.Value(),\n                IsQuiet = optQuiet.HasValue(),\n                IsVerbose = optVerbose.HasValue(),\n                RemainingArguments = app.RemainingArguments,\n                IsHelp = app.IsShowingInformation,\n                ListFiles = optList.HasValue(),\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-watch/DotNetWatcher.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Globalization;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.DotNet.Watcher.Internal;\nusing Microsoft.Extensions.CommandLineUtils;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.DotNet.Watcher\n{\n    public class DotNetWatcher\n    {\n        private readonly IReporter _reporter;\n        private readonly ProcessRunner _processRunner;\n\n        public DotNetWatcher(IReporter reporter)\n        {\n            Ensure.NotNull(reporter, nameof(reporter));\n\n            _reporter = reporter;\n            _processRunner = new ProcessRunner(reporter);\n        }\n\n        public async Task WatchAsync(ProcessSpec processSpec, IFileSetFactory fileSetFactory,\n            CancellationToken cancellationToken)\n        {\n            Ensure.NotNull(processSpec, nameof(processSpec));\n\n            var cancelledTaskSource = new TaskCompletionSource<object>();\n            cancellationToken.Register(state => ((TaskCompletionSource<object>) state).TrySetResult(null),\n                cancelledTaskSource);\n\n            var iteration = 1;\n\n            while (true)\n            {\n                processSpec.EnvironmentVariables[\"DOTNET_WATCH_ITERATION\"] = iteration.ToString(CultureInfo.InvariantCulture);\n                iteration++;\n\n                var fileSet = await fileSetFactory.CreateAsync(cancellationToken);\n\n                if (fileSet == null)\n                {\n                    _reporter.Error(\"Failed to find a list of files to watch\");\n                    return;\n                }\n\n                if (cancellationToken.IsCancellationRequested)\n                {\n                    return;\n                }\n\n                using (var currentRunCancellationSource = new CancellationTokenSource())\n                using (var combinedCancellationSource = CancellationTokenSource.CreateLinkedTokenSource(\n                    cancellationToken,\n                    currentRunCancellationSource.Token))\n                using (var fileSetWatcher = new FileSetWatcher(fileSet, _reporter))\n                {\n                    var fileSetTask = fileSetWatcher.GetChangedFileAsync(combinedCancellationSource.Token);\n                    var processTask = _processRunner.RunAsync(processSpec, combinedCancellationSource.Token);\n\n                    var args = ArgumentEscaper.EscapeAndConcatenate(processSpec.Arguments);\n                    _reporter.Verbose($\"Running {processSpec.ShortDisplayName()} with the following arguments: {args}\");\n\n                    _reporter.Output(\"Started\");\n\n                    var finishedTask = await Task.WhenAny(processTask, fileSetTask, cancelledTaskSource.Task);\n\n                    // Regardless of the which task finished first, make sure everything is cancelled\n                    // and wait for dotnet to exit. We don't want orphan processes\n                    currentRunCancellationSource.Cancel();\n\n                    await Task.WhenAll(processTask, fileSetTask);\n\n                    if (processTask.Result != 0 && finishedTask == processTask && !cancellationToken.IsCancellationRequested)\n                    {\n                        // Only show this error message if the process exited non-zero due to a normal process exit.\n                        // Don't show this if dotnet-watch killed the inner process due to file change or CTRL+C by the user\n                        _reporter.Error($\"Exited with error code {processTask.Result}\");\n                    }\n                    else\n                    {\n                        _reporter.Output(\"Exited\");\n                    }\n\n                    if (finishedTask == cancelledTaskSource.Task || cancellationToken.IsCancellationRequested)\n                    {\n                        return;\n                    }\n\n                    if (finishedTask == processTask)\n                    {\n                        _reporter.Warn(\"Waiting for a file to change before restarting dotnet...\");\n\n                        // Now wait for a file to change before restarting process\n                        await fileSetWatcher.GetChangedFileAsync(cancellationToken);\n                    }\n\n                    if (!string.IsNullOrEmpty(fileSetTask.Result))\n                    {\n                        _reporter.Output($\"File changed: {fileSetTask.Result}\");\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-watch/IFileSet.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.DotNet.Watcher\n{\n    public interface IFileSet : IEnumerable<string>\n    {\n        bool Contains(string filePath);\n    }\n}\n"
  },
  {
    "path": "src/dotnet-watch/IFileSetFactory.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Microsoft.DotNet.Watcher\n{\n    public interface IFileSetFactory\n    {\n        Task<IFileSet> CreateAsync(CancellationToken cancellationToken);\n    }\n}"
  },
  {
    "path": "src/dotnet-watch/Internal/FileSet.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace Microsoft.DotNet.Watcher.Internal\n{\n    public class FileSet : IFileSet\n    {\n        private readonly HashSet<string> _files;\n\n        public FileSet(IEnumerable<string> files)\n        {\n            _files = new HashSet<string>(files, StringComparer.OrdinalIgnoreCase);\n        }\n\n        public bool Contains(string filePath) => _files.Contains(filePath);\n\n        public int Count => _files.Count;\n\n        public IEnumerator<string> GetEnumerator() => _files.GetEnumerator();\n        IEnumerator IEnumerable.GetEnumerator() => _files.GetEnumerator();\n    }\n}\n"
  },
  {
    "path": "src/dotnet-watch/Internal/FileSetWatcher.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.DotNet.Watcher.Internal\n{\n    public class FileSetWatcher : IDisposable\n    {\n        private readonly FileWatcher _fileWatcher;\n        private readonly IFileSet _fileSet;\n\n        public FileSetWatcher(IFileSet fileSet, IReporter reporter)\n        {\n            Ensure.NotNull(fileSet, nameof(fileSet));\n\n            _fileSet = fileSet;\n            _fileWatcher = new FileWatcher(reporter);\n        }\n\n        public async Task<string> GetChangedFileAsync(CancellationToken cancellationToken)\n        {\n            foreach (var file in _fileSet)\n            {\n                _fileWatcher.WatchDirectory(Path.GetDirectoryName(file));\n            }\n\n            var tcs = new TaskCompletionSource<string>();\n            cancellationToken.Register(() => tcs.TrySetResult(null));\n\n            Action<string> callback = path =>\n            {\n                if (_fileSet.Contains(path))\n                {\n                    tcs.TrySetResult(path);\n                }\n            };\n\n            _fileWatcher.OnFileChange += callback;\n            var changedFile = await tcs.Task;\n            _fileWatcher.OnFileChange -= callback;\n\n            return changedFile;\n        }\n\n        public void Dispose()\n        {\n            _fileWatcher.Dispose();\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-watch/Internal/FileWatcher/DotnetFileWatcher.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.ComponentModel;\nusing System.IO;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.DotNet.Watcher.Internal\n{\n    internal class DotnetFileWatcher : IFileSystemWatcher\n    {\n        private volatile bool _disposed;\n\n        private readonly Func<string, FileSystemWatcher> _watcherFactory;\n\n        private FileSystemWatcher _fileSystemWatcher;\n\n        private readonly object _createLock = new object();\n\n        public DotnetFileWatcher(string watchedDirectory)\n            : this(watchedDirectory, DefaultWatcherFactory)\n        {\n        }\n\n        internal DotnetFileWatcher(string watchedDirectory, Func<string, FileSystemWatcher> fileSystemWatcherFactory)\n        {\n            Ensure.NotNull(fileSystemWatcherFactory, nameof(fileSystemWatcherFactory));\n            Ensure.NotNullOrEmpty(watchedDirectory, nameof(watchedDirectory));\n\n            BasePath = watchedDirectory;\n            _watcherFactory = fileSystemWatcherFactory;\n            CreateFileSystemWatcher();\n        }\n\n        public event EventHandler<string> OnFileChange;\n\n        public event EventHandler<Exception> OnError;\n\n        public string BasePath { get; }\n\n        private static FileSystemWatcher DefaultWatcherFactory(string watchedDirectory)\n        {\n            Ensure.NotNullOrEmpty(watchedDirectory, nameof(watchedDirectory));\n\n            return new FileSystemWatcher(watchedDirectory);\n        }\n\n        private void WatcherErrorHandler(object sender, ErrorEventArgs e)\n        {\n            if (_disposed)\n            {\n                return;\n            }\n\n            var exception = e.GetException();\n\n            // Win32Exception may be triggered when setting EnableRaisingEvents on a file system type\n            // that is not supported, such as a network share. Don't attempt to recreate the watcher\n            // in this case as it will cause a StackOverflowException\n            if (!(exception is Win32Exception))\n            {\n                // Recreate the watcher if it is a recoverable error.\n                CreateFileSystemWatcher();\n            }\n\n            OnError?.Invoke(this, exception);\n        }\n\n        private void WatcherRenameHandler(object sender, RenamedEventArgs e)\n        {\n            if (_disposed)\n            {\n                return;\n            }\n\n            NotifyChange(e.OldFullPath);\n            NotifyChange(e.FullPath);\n\n            if (Directory.Exists(e.FullPath))\n            {\n                foreach (var newLocation in Directory.EnumerateFileSystemEntries(e.FullPath, \"*\", SearchOption.AllDirectories))\n                {\n                    // Calculated previous path of this moved item.\n                    var oldLocation = Path.Combine(e.OldFullPath, newLocation.Substring(e.FullPath.Length + 1));\n                    NotifyChange(oldLocation);\n                    NotifyChange(newLocation);\n                }\n            }\n        }\n\n        private void WatcherChangeHandler(object sender, FileSystemEventArgs e)\n        {\n            if (_disposed)\n            {\n                return;\n            }\n\n            NotifyChange(e.FullPath);\n        }\n\n        private void NotifyChange(string fullPath)\n        {\n            // Only report file changes\n            OnFileChange?.Invoke(this, fullPath);\n        }\n\n        private void CreateFileSystemWatcher()\n        {\n            lock (_createLock)\n            {\n                bool enableEvents = false;\n\n                if (_fileSystemWatcher != null)\n                {\n                    enableEvents = _fileSystemWatcher.EnableRaisingEvents;\n\n                    DisposeInnerWatcher();\n                }\n\n                _fileSystemWatcher = _watcherFactory(BasePath);\n                _fileSystemWatcher.IncludeSubdirectories = true;\n\n                _fileSystemWatcher.Created += WatcherChangeHandler;\n                _fileSystemWatcher.Deleted += WatcherChangeHandler;\n                _fileSystemWatcher.Changed += WatcherChangeHandler;\n                _fileSystemWatcher.Renamed += WatcherRenameHandler;\n                _fileSystemWatcher.Error += WatcherErrorHandler;\n\n                _fileSystemWatcher.EnableRaisingEvents = enableEvents;\n            }\n        }\n\n        private void DisposeInnerWatcher()\n        {\n            _fileSystemWatcher.EnableRaisingEvents = false;\n\n            _fileSystemWatcher.Created -= WatcherChangeHandler;\n            _fileSystemWatcher.Deleted -= WatcherChangeHandler;\n            _fileSystemWatcher.Changed -= WatcherChangeHandler;\n            _fileSystemWatcher.Renamed -= WatcherRenameHandler;\n            _fileSystemWatcher.Error -= WatcherErrorHandler;\n\n            _fileSystemWatcher.Dispose();\n        }\n\n        public bool EnableRaisingEvents\n        {\n            get => _fileSystemWatcher.EnableRaisingEvents;\n            set => _fileSystemWatcher.EnableRaisingEvents = value;\n        }\n\n        public void Dispose()\n        {\n            _disposed = true;\n            DisposeInnerWatcher();\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-watch/Internal/FileWatcher/FileWatcherFactory.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\n\nnamespace Microsoft.DotNet.Watcher.Internal\n{\n    public static class FileWatcherFactory\n    {\n        public static IFileSystemWatcher CreateWatcher(string watchedDirectory)\n            => CreateWatcher(watchedDirectory, CommandLineOptions.IsPollingEnabled);\n\n        public static IFileSystemWatcher CreateWatcher(string watchedDirectory, bool usePollingWatcher)\n        {\n            return usePollingWatcher ?\n                new PollingFileWatcher(watchedDirectory) :\n                new DotnetFileWatcher(watchedDirectory) as IFileSystemWatcher;\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-watch/Internal/FileWatcher/IFileSystemWatcher.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\n\nnamespace Microsoft.DotNet.Watcher.Internal\n{\n    public interface IFileSystemWatcher : IDisposable\n    {\n        event EventHandler<string> OnFileChange;\n\n        event EventHandler<Exception> OnError;\n\n        string BasePath { get; }\n\n        bool EnableRaisingEvents { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-watch/Internal/FileWatcher/PollingFileWatcher.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Threading;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.DotNet.Watcher.Internal\n{\n    internal class PollingFileWatcher : IFileSystemWatcher\n    {\n        // The minimum interval to rerun the scan\n        private static readonly TimeSpan _minRunInternal = TimeSpan.FromSeconds(.5);\n\n        private readonly DirectoryInfo _watchedDirectory;\n\n        private Dictionary<string, FileMeta> _knownEntities = new Dictionary<string, FileMeta>();\n        private Dictionary<string, FileMeta> _tempDictionary = new Dictionary<string, FileMeta>();\n        private HashSet<string> _changes = new HashSet<string>();\n\n        private Thread _pollingThread;\n        private bool _raiseEvents;\n\n        private bool _disposed;\n\n        public PollingFileWatcher(string watchedDirectory)\n        {\n            Ensure.NotNullOrEmpty(watchedDirectory, nameof(watchedDirectory));\n\n            _watchedDirectory = new DirectoryInfo(watchedDirectory);\n            BasePath = _watchedDirectory.FullName;\n\n            _pollingThread = new Thread(new ThreadStart(PollingLoop));\n            _pollingThread.IsBackground = true;\n            _pollingThread.Name = nameof(PollingFileWatcher);\n\n            CreateKnownFilesSnapshot();\n\n            _pollingThread.Start();\n        }\n\n        public event EventHandler<string> OnFileChange;\n\n#pragma warning disable CS0067 // not used\n        public event EventHandler<Exception> OnError;\n#pragma warning restore\n\n        public string BasePath { get; }\n\n        public bool EnableRaisingEvents\n        {\n            get => _raiseEvents;\n            set\n            {\n                EnsureNotDisposed();\n                _raiseEvents = value;\n            }\n        }\n\n        private void PollingLoop()\n        {\n            var stopwatch = Stopwatch.StartNew();\n            stopwatch.Start();\n\n            while (!_disposed)\n            {\n                if (stopwatch.Elapsed < _minRunInternal)\n                {\n                    // Don't run too often\n                    // The min wait time here can be double\n                    // the value of the variable (FYI)\n                    Thread.Sleep(_minRunInternal);\n                }\n\n                stopwatch.Reset();\n\n                if (!_raiseEvents)\n                {\n                    continue;\n                }\n\n                CheckForChangedFiles();\n            }\n\n            stopwatch.Stop();\n        }\n\n        private void CreateKnownFilesSnapshot()\n        {\n            _knownEntities.Clear();\n\n            ForeachEntityInDirectory(_watchedDirectory, f =>\n            {\n                _knownEntities.Add(f.FullName, new FileMeta(f));\n            });\n        }\n\n        private void CheckForChangedFiles()\n        {\n            _changes.Clear();\n\n            ForeachEntityInDirectory(_watchedDirectory, f =>\n            {\n                var fullFilePath = f.FullName;\n\n                if (!_knownEntities.ContainsKey(fullFilePath))\n                {\n                    // New file\n                    RecordChange(f);\n                }\n                else\n                {\n                    var fileMeta = _knownEntities[fullFilePath];\n\n                    try\n                    {\n                        if (fileMeta.FileInfo.LastWriteTime != f.LastWriteTime)\n                        {\n                            // File changed\n                            RecordChange(f);\n                        }\n\n                        _knownEntities[fullFilePath] = new FileMeta(fileMeta.FileInfo, true);\n                    }\n                    catch (FileNotFoundException)\n                    {\n                        _knownEntities[fullFilePath] = new FileMeta(fileMeta.FileInfo, false);\n                    }\n                }\n\n                _tempDictionary.Add(f.FullName, new FileMeta(f));\n            });\n\n            foreach (var file in _knownEntities)\n            {\n                if (!file.Value.FoundAgain)\n                {\n                    // File deleted\n                    RecordChange(file.Value.FileInfo);\n                }\n            }\n\n            NotifyChanges();\n\n            // Swap the two dictionaries\n            var swap = _knownEntities;\n            _knownEntities = _tempDictionary;\n            _tempDictionary = swap;\n\n            _tempDictionary.Clear();\n        }\n\n        private void RecordChange(FileSystemInfo fileInfo)\n        {\n            if (fileInfo == null ||\n                _changes.Contains(fileInfo.FullName) ||\n                fileInfo.FullName.Equals(_watchedDirectory.FullName, StringComparison.Ordinal))\n            {\n                return;\n            }\n\n            _changes.Add(fileInfo.FullName);\n            if (fileInfo.FullName != _watchedDirectory.FullName)\n            {\n                var file = fileInfo as FileInfo;\n                if (file != null)\n                {\n                    RecordChange(file.Directory);\n                }\n                else\n                {\n                    var dir = fileInfo as DirectoryInfo;\n                    if (dir != null)\n                    {\n                        RecordChange(dir.Parent);\n                    }\n                }\n            }\n        }\n\n        private void ForeachEntityInDirectory(DirectoryInfo dirInfo, Action<FileSystemInfo> fileAction)\n        {\n            if (!dirInfo.Exists)\n            {\n                return;\n            }\n\n            var entities = dirInfo.EnumerateFileSystemInfos(\"*.*\");\n            foreach (var entity in entities)\n            {\n                fileAction(entity);\n\n                var subdirInfo = entity as DirectoryInfo;\n                if (subdirInfo != null)\n                {\n                    ForeachEntityInDirectory(subdirInfo, fileAction);\n                }\n            }\n        }\n\n        private void NotifyChanges()\n        {\n            foreach (var path in _changes)\n            {\n                if (_disposed || !_raiseEvents)\n                {\n                    break;\n                }\n\n                if (OnFileChange != null)\n                {\n                    OnFileChange(this, path);\n                }\n            }\n        }\n\n        private void EnsureNotDisposed()\n        {\n            if (_disposed)\n            {\n                throw new ObjectDisposedException(nameof(PollingFileWatcher));\n            }\n        }\n\n        public void Dispose()\n        {\n            EnableRaisingEvents = false;\n            _disposed = true;\n        }\n\n        private struct FileMeta\n        {\n            public FileMeta(FileSystemInfo fileInfo, bool foundAgain = false)\n            {\n                FileInfo = fileInfo;\n                FoundAgain = foundAgain;\n            }\n\n            public FileSystemInfo FileInfo;\n\n            public bool FoundAgain;\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-watch/Internal/FileWatcher.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.DotNet.Watcher.Internal\n{\n    public class FileWatcher\n    {\n        private bool _disposed;\n\n        private readonly IDictionary<string, IFileSystemWatcher> _watchers;\n        private readonly IReporter _reporter;\n\n        public FileWatcher()\n            : this(NullReporter.Singleton)\n        { }\n\n        public FileWatcher(IReporter reporter)\n        {\n            _reporter = reporter ?? throw new ArgumentNullException(nameof(reporter));\n            _watchers = new Dictionary<string, IFileSystemWatcher>();\n        }\n\n        public event Action<string> OnFileChange;\n\n        public void WatchDirectory(string directory)\n        {\n            EnsureNotDisposed();\n            AddDirectoryWatcher(directory);\n        }\n\n        public void Dispose()\n        {\n            if (_disposed)\n            {\n                return;\n            }\n\n            _disposed = true;\n\n            foreach (var watcher in _watchers)\n            {\n                watcher.Value.OnFileChange -= WatcherChangedHandler;\n                watcher.Value.OnError -= WatcherErrorHandler;\n                watcher.Value.Dispose();\n            }\n\n            _watchers.Clear();\n        }\n\n        private void AddDirectoryWatcher(string directory)\n        {\n            directory = EnsureTrailingSlash(directory);\n\n            var alreadyWatched = _watchers\n                .Where(d => directory.StartsWith(d.Key))\n                .Any();\n\n            if (alreadyWatched)\n            {\n                return;\n            }\n\n            var redundantWatchers = _watchers\n                .Where(d => d.Key.StartsWith(directory))\n                .Select(d => d.Key)\n                .ToList();\n\n            if (redundantWatchers.Any())\n            {\n                foreach (var watcher in redundantWatchers)\n                {\n                    DisposeWatcher(watcher);\n                }\n            }\n\n            var newWatcher = FileWatcherFactory.CreateWatcher(directory);\n            newWatcher.OnFileChange += WatcherChangedHandler;\n            newWatcher.OnError += WatcherErrorHandler;\n            newWatcher.EnableRaisingEvents = true;\n\n            _watchers.Add(directory, newWatcher);\n        }\n\n        private void WatcherErrorHandler(object sender, Exception error)\n        {\n            if (sender is IFileSystemWatcher watcher)\n            {\n                _reporter.Warn($\"The file watcher observing '{watcher.BasePath}' encountered an error: {error.Message}\");\n            }\n        }\n\n        private void WatcherChangedHandler(object sender, string changedPath)\n        {\n            NotifyChange(changedPath);\n        }\n\n        private void NotifyChange(string path)\n        {\n            if (OnFileChange != null)\n            {\n                OnFileChange(path);\n            }\n        }\n\n        private void DisposeWatcher(string directory)\n        {\n            var watcher = _watchers[directory];\n            _watchers.Remove(directory);\n\n            watcher.EnableRaisingEvents = false;\n\n            watcher.OnFileChange -= WatcherChangedHandler;\n            watcher.OnError -= WatcherErrorHandler;\n\n            watcher.Dispose();\n        }\n\n        private void EnsureNotDisposed()\n        {\n            if (_disposed)\n            {\n                throw new ObjectDisposedException(nameof(FileWatcher));\n            }\n        }\n\n        private static string EnsureTrailingSlash(string path)\n        {\n            if (!string.IsNullOrEmpty(path) &&\n                path[path.Length - 1] != Path.DirectorySeparatorChar)\n            {\n                return path + Path.DirectorySeparatorChar;\n            }\n\n            return path;\n        }\n    }\n}"
  },
  {
    "path": "src/dotnet-watch/Internal/MsBuildFileSetFactory.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Extensions.CommandLineUtils;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.DotNet.Watcher.Internal\n{\n    public class MsBuildFileSetFactory : IFileSetFactory\n    {\n        private const string TargetName = \"GenerateWatchList\";\n        private const string WatchTargetsFileName = \"DotNetWatch.targets\";\n        private readonly IReporter _reporter;\n        private readonly string _projectFile;\n        private readonly OutputSink _outputSink;\n        private readonly ProcessRunner _processRunner;\n        private readonly bool _waitOnError;\n        private readonly IReadOnlyList<string> _buildFlags;\n\n        public MsBuildFileSetFactory(IReporter reporter,\n            string projectFile,\n            bool waitOnError,\n            bool trace)\n            : this(reporter, projectFile, new OutputSink(), trace)\n        {\n            _waitOnError = waitOnError;\n        }\n\n        // output sink is for testing\n        internal MsBuildFileSetFactory(IReporter reporter,\n            string projectFile,\n            OutputSink outputSink,\n            bool trace)\n        {\n            Ensure.NotNull(reporter, nameof(reporter));\n            Ensure.NotNullOrEmpty(projectFile, nameof(projectFile));\n            Ensure.NotNull(outputSink, nameof(outputSink));\n\n            _reporter = reporter;\n            _projectFile = projectFile;\n            _outputSink = outputSink;\n            _processRunner = new ProcessRunner(reporter);\n            _buildFlags = InitializeArgs(FindTargetsFile(), trace);\n        }\n\n        public async Task<IFileSet> CreateAsync(CancellationToken cancellationToken)\n        {\n            var watchList = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());\n            try\n            {\n                var projectDir = Path.GetDirectoryName(_projectFile);\n\n                while (true)\n                {\n                    cancellationToken.ThrowIfCancellationRequested();\n\n                    var capture = _outputSink.StartCapture();\n                    // TODO adding files doesn't currently work. Need to provide a way to detect new files\n                    // find files\n                    var processSpec = new ProcessSpec\n                    {\n                        Executable = DotNetMuxer.MuxerPathOrDefault(),\n                        WorkingDirectory = projectDir,\n                        Arguments = new[]\n                        {\n                            \"msbuild\",\n                            _projectFile,\n                            $\"/p:_DotNetWatchListFile={watchList}\"\n                        }.Concat(_buildFlags),\n                        OutputCapture = capture\n                    };\n\n                    _reporter.Verbose($\"Running MSBuild target '{TargetName}' on '{_projectFile}'\");\n\n                    var exitCode = await _processRunner.RunAsync(processSpec, cancellationToken);\n\n                    if (exitCode == 0 && File.Exists(watchList))\n                    {\n                        var fileset = new FileSet(\n                            File.ReadAllLines(watchList)\n                                .Select(l => l?.Trim())\n                                .Where(l => !string.IsNullOrEmpty(l)));\n\n                        _reporter.Verbose($\"Watching {fileset.Count} file(s) for changes\");\n#if DEBUG\n\n                        foreach (var file in fileset)\n                        {\n                            _reporter.Verbose($\"  -> {file}\");\n                        }\n\n                        Debug.Assert(fileset.All(Path.IsPathRooted), \"All files should be rooted paths\");\n#endif\n\n                        return fileset;\n                    }\n\n                    _reporter.Error($\"Error(s) finding watch items project file '{Path.GetFileName(_projectFile)}'\");\n\n                    _reporter.Output($\"MSBuild output from target '{TargetName}':\");\n                    _reporter.Output(string.Empty);\n\n                    foreach (var line in capture.Lines)\n                    {\n                        _reporter.Output($\"   {line}\");\n                    }\n\n                    _reporter.Output(string.Empty);\n\n                    if (!_waitOnError)\n                    {\n                        return null;\n                    }\n                    else\n                    {\n                        _reporter.Warn(\"Fix the error to continue or press Ctrl+C to exit.\");\n\n                        var fileSet = new FileSet(new[] { _projectFile });\n\n                        using (var watcher = new FileSetWatcher(fileSet, _reporter))\n                        {\n                            await watcher.GetChangedFileAsync(cancellationToken);\n\n                            _reporter.Output($\"File changed: {_projectFile}\");\n                        }\n                    }\n                }\n            }\n            finally\n            {\n                if (File.Exists(watchList))\n                {\n                    File.Delete(watchList);\n                }\n            }\n        }\n\n        private IReadOnlyList<string> InitializeArgs(string watchTargetsFile, bool trace)\n        {\n            var args = new List<string>\n            {\n                \"/nologo\",\n                \"/v:n\",\n                \"/t:\" + TargetName,\n                \"/p:DotNetWatchBuild=true\", // extensibility point for users\n                \"/p:DesignTimeBuild=true\", // don't do expensive things\n                \"/p:CustomAfterMicrosoftCommonTargets=\" + watchTargetsFile,\n                \"/p:CustomAfterMicrosoftCommonCrossTargetingTargets=\" + watchTargetsFile,\n            };\n\n            if (trace)\n            {\n                // enables capturing markers to know which projects have been visited\n                args.Add(\"/p:_DotNetWatchTraceOutput=true\");\n            }\n\n            return args;\n        }\n\n        private string FindTargetsFile()\n        {\n            var assemblyDir = Path.GetDirectoryName(typeof(MsBuildFileSetFactory).Assembly.Location);\n            var searchPaths = new[]\n            {\n                Path.Combine(AppContext.BaseDirectory, \"assets\"),\n                Path.Combine(assemblyDir, \"assets\"),\n                AppContext.BaseDirectory,\n                assemblyDir,\n            };\n\n            var targetPath = searchPaths.Select(p => Path.Combine(p, WatchTargetsFileName)).FirstOrDefault(File.Exists);\n            if (targetPath == null)\n            {\n                _reporter.Error(\"Fatal error: could not find DotNetWatch.targets\");\n                return null;\n            }\n            return targetPath;\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-watch/Internal/MsBuildProjectFinder.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing Microsoft.DotNet.Watcher.Tools;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.DotNet.Watcher.Internal\n{\n    internal class MsBuildProjectFinder\n    {\n        /// <summary>\n        /// Finds a compatible MSBuild project.\n        /// <param name=\"searchBase\">The base directory to search</param>\n        /// <param name=\"project\">The filename of the project. Can be null.</param>\n        /// </summary>\n        public static string FindMsBuildProject(string searchBase, string project)\n        {\n            Ensure.NotNullOrEmpty(searchBase, nameof(searchBase));\n\n            var projectPath = project ?? searchBase;\n\n            if (!Path.IsPathRooted(projectPath))\n            {\n                projectPath = Path.Combine(searchBase, projectPath);\n            }\n\n            if (Directory.Exists(projectPath))\n            {\n                var projects = Directory.EnumerateFileSystemEntries(projectPath, \"*.*proj\", SearchOption.TopDirectoryOnly)\n                    .Where(f => !\".xproj\".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase))\n                    .ToList();\n\n                if (projects.Count > 1)\n                {\n                    throw new FileNotFoundException(Resources.FormatError_MultipleProjectsFound(projectPath));\n                }\n\n                if (projects.Count == 0)\n                {\n                    throw new FileNotFoundException(Resources.FormatError_NoProjectsFound(projectPath));\n                }\n\n                return projects[0];\n            }\n\n            if (!File.Exists(projectPath))\n            {\n                throw new FileNotFoundException(Resources.FormatError_ProjectPath_NotFound(projectPath));\n            }\n\n            return projectPath;\n        }\n    }\n}"
  },
  {
    "path": "src/dotnet-watch/Internal/OutputCapture.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.DotNet.Watcher.Internal\n{\n    public class OutputCapture\n    {\n        private readonly List<string> _lines = new List<string>();\n        public IEnumerable<string> Lines => _lines;\n        public void AddLine(string line) => _lines.Add(line);\n    }\n}"
  },
  {
    "path": "src/dotnet-watch/Internal/OutputSink.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.DotNet.Watcher.Internal\n{\n    public class OutputSink\n    {\n        public OutputCapture Current { get; private set; }\n        public OutputCapture StartCapture()\n        {\n            return (Current = new OutputCapture());\n        }\n    }\n}"
  },
  {
    "path": "src/dotnet-watch/Internal/ProcessRunner.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Extensions.CommandLineUtils;\nusing Microsoft.Extensions.Internal;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.DotNet.Watcher.Internal\n{\n    public class ProcessRunner\n    {\n        private readonly IReporter _reporter;\n\n        public ProcessRunner(IReporter reporter)\n        {\n            Ensure.NotNull(reporter, nameof(reporter));\n\n            _reporter = reporter;\n        }\n\n        // May not be necessary in the future. See https://github.com/dotnet/corefx/issues/12039\n        public async Task<int> RunAsync(ProcessSpec processSpec, CancellationToken cancellationToken)\n        {\n            Ensure.NotNull(processSpec, nameof(processSpec));\n\n            int exitCode;\n\n            var stopwatch = new Stopwatch();\n\n            using (var process = CreateProcess(processSpec))\n            using (var processState = new ProcessState(process, _reporter))\n            {\n                cancellationToken.Register(() => processState.TryKill());\n\n                stopwatch.Start();\n                process.Start();\n                _reporter.Verbose($\"Started '{processSpec.Executable}' with process id {process.Id}\");\n\n                if (processSpec.IsOutputCaptured)\n                {\n                    await Task.WhenAll(\n                        processState.Task,\n                        ConsumeStreamAsync(process.StandardOutput, processSpec.OutputCapture.AddLine),\n                        ConsumeStreamAsync(process.StandardError, processSpec.OutputCapture.AddLine)\n                    );\n                }\n                else\n                {\n                    await processState.Task;\n                }\n\n                exitCode = process.ExitCode;\n                stopwatch.Stop();\n                _reporter.Verbose($\"Process id {process.Id} ran for {stopwatch.ElapsedMilliseconds}ms\");\n            }\n\n            return exitCode;\n        }\n\n        private Process CreateProcess(ProcessSpec processSpec)\n        {\n            var process = new Process\n            {\n                EnableRaisingEvents = true,\n                StartInfo =\n                {\n                    FileName = processSpec.Executable,\n                    Arguments = ArgumentEscaper.EscapeAndConcatenate(processSpec.Arguments),\n                    UseShellExecute = false,\n                    WorkingDirectory = processSpec.WorkingDirectory,\n                    RedirectStandardOutput = processSpec.IsOutputCaptured,\n                    RedirectStandardError = processSpec.IsOutputCaptured,\n                }\n            };\n\n            foreach (var env in processSpec.EnvironmentVariables)\n            {\n                process.StartInfo.Environment.Add(env.Key, env.Value);\n            }\n\n            return process;\n        }\n\n        private static async Task ConsumeStreamAsync(StreamReader reader, Action<string> consume)\n        {\n            string line;\n            while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) != null)\n            {\n                consume?.Invoke(line);\n            }\n        }\n\n        private class ProcessState : IDisposable\n        {\n            private readonly IReporter _reporter;\n            private readonly Process _process;\n            private readonly TaskCompletionSource<object> _tcs = new TaskCompletionSource<object>();\n            private volatile bool _disposed;\n\n            public ProcessState(Process process, IReporter reporter)\n            {\n                _reporter = reporter;\n                _process = process;\n                _process.Exited += OnExited;\n                Task = _tcs.Task.ContinueWith(_ =>\n                {\n                    try\n                    {\n                        // We need to use two WaitForExit calls to ensure that all of the output/events are processed. Previously\n                        // this code used Process.Exited, which could result in us missing some output due to the ordering of\n                        // events.\n                        //\n                        // See the remarks here: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.waitforexit#System_Diagnostics_Process_WaitForExit_System_Int32_\n                        if (!_process.WaitForExit(Int32.MaxValue))\n                        {\n                            throw new TimeoutException();\n                        }\n\n                        _process.WaitForExit();\n                    }\n                    catch (InvalidOperationException)\n                    {\n                        // suppress if this throws if no process is associated with this object anymore.\n                    }\n                });\n            }\n\n            public Task Task { get; }\n\n            public void TryKill()\n            {\n                if (_disposed)\n                {\n                    return;\n                }\n\n                try\n                {\n                    if (!_process.HasExited)\n                    {\n                        _reporter.Verbose($\"Killing process {_process.Id}\");\n                        _process.KillTree();\n                    }\n                }\n                catch (Exception ex)\n                {\n                    _reporter.Verbose($\"Error while killing process '{_process.StartInfo.FileName} {_process.StartInfo.Arguments}': {ex.Message}\");\n#if DEBUG\n                    _reporter.Verbose(ex.ToString());\n#endif\n                }\n            }\n\n            private void OnExited(object sender, EventArgs args)\n                => _tcs.TrySetResult(null);\n\n            public void Dispose()\n            {\n                if (!_disposed)\n                {\n                    TryKill();\n                    _disposed = true;\n                    _process.Exited -= OnExited;\n                    _process.Dispose();\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-watch/PrefixConsoleReporter.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.DotNet.Watcher\n{\n    public class PrefixConsoleReporter : ConsoleReporter\n    {\n        private object _lock = new object();\n\n        public PrefixConsoleReporter(IConsole console, bool verbose, bool quiet)\n            : base(console, verbose, quiet)\n        { }\n\n        protected override void WriteLine(TextWriter writer, string message, ConsoleColor? color)\n        {\n            const string prefix = \"watch : \";\n\n            lock (_lock)\n            {\n                Console.ForegroundColor = ConsoleColor.DarkGray;\n                writer.Write(prefix);\n                Console.ResetColor();\n\n                base.WriteLine(writer, message, color);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-watch/ProcessSpec.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing System.IO;\nusing Microsoft.DotNet.Watcher.Internal;\n\nnamespace Microsoft.DotNet.Watcher\n{\n    public class ProcessSpec\n    {\n        public string Executable { get; set; }\n        public string WorkingDirectory { get; set; }\n        public IDictionary<string, string> EnvironmentVariables { get; } = new Dictionary<string, string>();\n        public IEnumerable<string> Arguments { get; set; }\n        public OutputCapture OutputCapture { get; set; }\n\n        public string ShortDisplayName()\n            => Path.GetFileNameWithoutExtension(Executable);\n\n        public bool IsOutputCaptured => OutputCapture != null;\n    }\n}\n"
  },
  {
    "path": "src/dotnet-watch/Program.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.DotNet.Watcher.Internal;\nusing Microsoft.Extensions.CommandLineUtils;\nusing Microsoft.Extensions.Tools.Internal;\n\nnamespace Microsoft.DotNet.Watcher\n{\n    public class Program : IDisposable\n    {\n        private readonly IConsole _console;\n        private readonly string _workingDir;\n        private readonly CancellationTokenSource _cts;\n        private IReporter _reporter;\n\n        public Program(IConsole console, string workingDir)\n        {\n            Ensure.NotNull(console, nameof(console));\n            Ensure.NotNullOrEmpty(workingDir, nameof(workingDir));\n\n            _console = console;\n            _workingDir = workingDir;\n            _cts = new CancellationTokenSource();\n            _console.CancelKeyPress += OnCancelKeyPress;\n            _reporter = CreateReporter(verbose: true, quiet: false, console: _console);\n        }\n\n        public static async Task<int> Main(string[] args)\n        {\n            try\n            {\n                DebugHelper.HandleDebugSwitch(ref args);\n                using (var program = new Program(PhysicalConsole.Singleton, Directory.GetCurrentDirectory()))\n                {\n                    return await program.RunAsync(args);\n                }\n            }\n            catch (Exception ex)\n            {\n                Console.Error.WriteLine(\"Unexpected error:\");\n                Console.Error.WriteLine(ex.ToString());\n                return 1;\n            }\n        }\n\n        public async Task<int> RunAsync(string[] args)\n        {\n            CommandLineOptions options;\n            try\n            {\n                options = CommandLineOptions.Parse(args, _console);\n            }\n            catch (CommandParsingException ex)\n            {\n                _reporter.Error(ex.Message);\n                return 1;\n            }\n\n            if (options == null)\n            {\n                // invalid args syntax\n                return 1;\n            }\n\n            if (options.IsHelp)\n            {\n                return 2;\n            }\n\n            // update reporter as configured by options\n            _reporter = CreateReporter(options.IsVerbose, options.IsQuiet, _console);\n\n            try\n            {\n                if (_cts.IsCancellationRequested)\n                {\n                    return 1;\n                }\n\n                if (options.ListFiles)\n                {\n                    return await ListFilesAsync(_reporter,\n                        options.Project,\n                        _cts.Token);\n                }\n                else\n                {\n                    return await MainInternalAsync(_reporter,\n                        options.Project,\n                        options.RemainingArguments,\n                        _cts.Token);\n                }\n            }\n            catch (Exception ex)\n            {\n                if (ex is TaskCanceledException || ex is OperationCanceledException)\n                {\n                    // swallow when only exception is the CTRL+C forced an exit\n                    return 0;\n                }\n\n                _reporter.Error(ex.ToString());\n                _reporter.Error(\"An unexpected error occurred\");\n                return 1;\n            }\n        }\n\n        private void OnCancelKeyPress(object sender, ConsoleCancelEventArgs args)\n        {\n            // suppress CTRL+C on the first press\n            args.Cancel = !_cts.IsCancellationRequested;\n\n            if (args.Cancel)\n            {\n                _reporter.Output(\"Shutdown requested. Press Ctrl+C again to force exit.\");\n            }\n\n            _cts.Cancel();\n        }\n\n        private async Task<int> MainInternalAsync(\n            IReporter reporter,\n            string project,\n            ICollection<string> args,\n            CancellationToken cancellationToken)\n        {\n            // TODO multiple projects should be easy enough to add here\n            string projectFile;\n            try\n            {\n                projectFile = MsBuildProjectFinder.FindMsBuildProject(_workingDir, project);\n            }\n            catch (FileNotFoundException ex)\n            {\n                reporter.Error(ex.Message);\n                return 1;\n            }\n\n            var fileSetFactory = new MsBuildFileSetFactory(reporter,\n                projectFile,\n                waitOnError: true,\n                trace: false);\n            var processInfo = new ProcessSpec\n            {\n                Executable = DotNetMuxer.MuxerPathOrDefault(),\n                WorkingDirectory = Path.GetDirectoryName(projectFile),\n                Arguments = args,\n                EnvironmentVariables =\n                {\n                    [\"DOTNET_WATCH\"] = \"1\"\n                },\n            };\n\n            if (CommandLineOptions.IsPollingEnabled)\n            {\n                _reporter.Output(\"Polling file watcher is enabled\");\n            }\n\n            await new DotNetWatcher(reporter)\n                .WatchAsync(processInfo, fileSetFactory, cancellationToken);\n\n            return 0;\n        }\n\n        private async Task<int> ListFilesAsync(\n            IReporter reporter,\n            string project,\n            CancellationToken cancellationToken)\n        {\n            // TODO multiple projects should be easy enough to add here\n            string projectFile;\n            try\n            {\n                projectFile = MsBuildProjectFinder.FindMsBuildProject(_workingDir, project);\n            }\n            catch (FileNotFoundException ex)\n            {\n                reporter.Error(ex.Message);\n                return 1;\n            }\n\n            var fileSetFactory = new MsBuildFileSetFactory(reporter,\n                projectFile,\n                waitOnError: false,\n                trace: false);\n            var files = await fileSetFactory.CreateAsync(cancellationToken);\n\n            if (files == null)\n            {\n                return 1;\n            }\n\n            foreach (var file in files)\n            {\n                _console.Out.WriteLine(file);\n            }\n\n            return 0;\n        }\n\n        private static IReporter CreateReporter(bool verbose, bool quiet, IConsole console)\n            => new PrefixConsoleReporter(console, verbose || CliContext.IsGlobalVerbose(), quiet);\n\n        public void Dispose()\n        {\n            _console.CancelKeyPress -= OnCancelKeyPress;\n            _cts.Dispose();\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-watch/Properties/AssemblyInfo.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Runtime.CompilerServices;\n\n[assembly: InternalsVisibleTo(\"Microsoft.DotNet.Watcher.Tools.Tests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb\")]\n"
  },
  {
    "path": "src/dotnet-watch/Properties/Resources.Designer.cs",
    "content": "// <auto-generated />\nnamespace Microsoft.DotNet.Watcher.Tools\n{\n    using System.Globalization;\n    using System.Reflection;\n    using System.Resources;\n\n    internal static class Resources\n    {\n        private static readonly ResourceManager _resourceManager\n            = new ResourceManager(\"Microsoft.DotNet.Watcher.Tools.Resources\", typeof(Resources).GetTypeInfo().Assembly);\n\n        /// <summary>\n        /// The project file '{path}' does not exist.\n        /// </summary>\n        internal static string Error_ProjectPath_NotFound\n        {\n            get { return GetString(\"Error_ProjectPath_NotFound\"); }\n        }\n\n        /// <summary>\n        /// The project file '{path}' does not exist.\n        /// </summary>\n        internal static string FormatError_ProjectPath_NotFound(object path)\n        {\n            return string.Format(CultureInfo.CurrentCulture, GetString(\"Error_ProjectPath_NotFound\", \"path\"), path);\n        }\n\n        /// <summary>\n        /// Multiple MSBuild project files found in '{projectPath}'. Specify which to use with the --project option.\n        /// </summary>\n        internal static string Error_MultipleProjectsFound\n        {\n            get { return GetString(\"Error_MultipleProjectsFound\"); }\n        }\n\n        /// <summary>\n        /// Multiple MSBuild project files found in '{projectPath}'. Specify which to use with the --project option.\n        /// </summary>\n        internal static string FormatError_MultipleProjectsFound(object projectPath)\n        {\n            return string.Format(CultureInfo.CurrentCulture, GetString(\"Error_MultipleProjectsFound\", \"projectPath\"), projectPath);\n        }\n\n        /// <summary>\n        /// Could not find a MSBuild project file in '{projectPath}'. Specify which project to use with the --project option.\n        /// </summary>\n        internal static string Error_NoProjectsFound\n        {\n            get { return GetString(\"Error_NoProjectsFound\"); }\n        }\n\n        /// <summary>\n        /// Could not find a MSBuild project file in '{projectPath}'. Specify which project to use with the --project option.\n        /// </summary>\n        internal static string FormatError_NoProjectsFound(object projectPath)\n        {\n            return string.Format(CultureInfo.CurrentCulture, GetString(\"Error_NoProjectsFound\", \"projectPath\"), projectPath);\n        }\n\n        /// <summary>\n        /// Cannot specify both '--quiet' and '--verbose' options.\n        /// </summary>\n        internal static string Error_QuietAndVerboseSpecified\n        {\n            get { return GetString(\"Error_QuietAndVerboseSpecified\"); }\n        }\n\n        /// <summary>\n        /// Cannot specify both '--quiet' and '--verbose' options.\n        /// </summary>\n        internal static string FormatError_QuietAndVerboseSpecified()\n        {\n            return GetString(\"Error_QuietAndVerboseSpecified\");\n        }\n\n        private static string GetString(string name, params string[] formatterNames)\n        {\n            var value = _resourceManager.GetString(name);\n\n            System.Diagnostics.Debug.Assert(value != null);\n\n            if (formatterNames != null)\n            {\n                for (var i = 0; i < formatterNames.Length; i++)\n                {\n                    value = value.Replace(\"{\" + formatterNames[i] + \"}\", \"{\" + i + \"}\");\n                }\n            }\n\n            return value;\n        }\n    }\n}\n"
  },
  {
    "path": "src/dotnet-watch/README.md",
    "content": "dotnet-watch\n============\n`dotnet-watch` is a file watcher for `dotnet` that restarts the specified application when changes in the source code are detected.\n\n### How To Use\n\nThe command must be executed in the directory that contains the project to be watched.\n\n    Usage: dotnet watch [options] [[--] <args>...]\n\n    Options:\n      -?|-h|--help  Show help information\n      -q|--quiet    Suppresses all output except warnings and errors\n      -v|--verbose  Show verbose output\n\nAdd `watch` after `dotnet` and before the command arguments that you want to run:\n\n| What you want to run                           | Dotnet watch command                                     |\n| ---------------------------------------------- | -------------------------------------------------------- |\n| dotnet run                                     | dotnet **watch** run                                     |\n| dotnet run --arg1 value1                       | dotnet **watch** run --arg1 value                        |\n| dotnet run --framework net451 -- --arg1 value1 | dotnet **watch** run --framework net451 -- --arg1 value1 |\n| dotnet test                                    | dotnet **watch** test                                    |\n\n### Environment variables\n\nSome configuration options can be passed to `dotnet watch` through environment variables. The available variables are:\n\n| Variable                                       | Effect                                                   |\n| ---------------------------------------------- | -------------------------------------------------------- |\n| 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.                       |\n\n### MSBuild\n\ndotnet-watch can be configured from the MSBuild project file being watched.\n\n**Watch items**\n\ndotnet-watch will watch all items in the **Watch** item group.\nBy default, this group inclues all items in **Compile** and **EmbeddedResource**.\n\nMore items can be added to watch in a project file by adding items to 'Watch'.\n\n```xml\n<ItemGroup>\n    <!-- extends watching group to include *.js files -->\n    <Watch Include=\"**\\*.js\" Exclude=\"node_modules\\**\\*.js;$(DefaultExcludes)\" />\n</ItemGroup>\n```\n\ndotnet-watch will ignore Compile and EmbeddedResource items with the `Watch=\"false\"` attribute.\n\nExample:\n\n```xml\n<ItemGroup>\n    <!-- exclude Generated.cs from dotnet-watch -->\n    <Compile Update=\"Generated.cs\" Watch=\"false\" />\n    <!-- exclude Strings.resx from dotnet-watch -->\n    <EmbeddedResource Update=\"Strings.resx\" Watch=\"false\" />\n</ItemGroup>\n```\n\n**Project References**\n\nBy default, dotnet-watch will scan the entire graph of project references and watch all files within those projects.\n\ndotnet-watch will ignore project references with the `Watch=\"false\"` attribute.\n\n```xml\n<ItemGroup>\n  <ProjectReference Include=\"..\\ClassLibrary1\\ClassLibrary1.csproj\" Watch=\"false\" />\n</ItemGroup>\n```\n\n\n**Advanced configuration**\n\ndotnet-watch performs a design-time build to find items to watch.\nWhen this build is run, dotnet-watch will set the property `DotNetWatchBuild=true`.\n\nExample:\n\n```xml\n  <ItemGroup Condition=\"'$(DotNetWatchBuild)'=='true'\">\n    <!-- only included in the project when dotnet-watch is running -->\n  </ItemGroup>\n```\n"
  },
  {
    "path": "src/dotnet-watch/Resources.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!--\n    Microsoft ResX Schema\n\n    Version 2.0\n\n    The primary goals of this format is to allow a simple XML format\n    that is mostly human readable. The generation and parsing of the\n    various data types are done through the TypeConverter classes\n    associated with the data types.\n\n    Example:\n\n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n\n    There are any number of \"resheader\" rows that contain simple\n    name/value pairs.\n\n    Each data row contains a name, and value. The row also contains a\n    type or mimetype. Type corresponds to a .NET class that support\n    text/value conversion through the TypeConverter architecture.\n    Classes that don't support this are serialized and stored with the\n    mimetype set.\n\n    The mimetype is used for serialized objects, and tells the\n    ResXResourceReader how to depersist the object. This is currently not\n    extensible. For a given mimetype the value must be set accordingly:\n\n    Note - application/x-microsoft.net.object.binary.base64 is the format\n    that the ResXResourceWriter will generate, however the reader can\n    read any of the formats listed below.\n\n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array\n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"Error_ProjectPath_NotFound\" xml:space=\"preserve\">\n    <value>The project file '{path}' does not exist.</value>\n  </data>\n  <data name=\"Error_MultipleProjectsFound\" xml:space=\"preserve\">\n    <value>Multiple MSBuild project files found in '{projectPath}'. Specify which to use with the --project option.</value>\n  </data>\n  <data name=\"Error_NoProjectsFound\" xml:space=\"preserve\">\n    <value>Could not find a MSBuild project file in '{projectPath}'. Specify which project to use with the --project option.</value>\n  </data>\n  <data name=\"Error_QuietAndVerboseSpecified\" xml:space=\"preserve\">\n    <value>Cannot specify both '--quiet' and '--verbose' options.</value>\n  </data>\n</root>"
  },
  {
    "path": "src/dotnet-watch/assets/DotNetWatch.targets",
    "content": "<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n<!--\n=========================================================================\nGenerateWatchList\n\nMain target called by dotnet-watch. It gathers MSBuild items and writes\nthem to a file.\n=========================================================================\n-->\n  <Target Name=\"GenerateWatchList\"\n          DependsOnTargets=\"_CollectWatchItems\">\n    <WriteLinesToFile Overwrite=\"true\"\n                      File=\"$(_DotNetWatchListFile)\"\n                      Lines=\"@(Watch -> '%(FullPath)')\" />\n  </Target>\n\n<!--\n=========================================================================\n_CollectWatchItems\n\nGathers all files to be watched.\nReturns: @(Watch)\n=========================================================================\n-->\n  <PropertyGroup>\n    <_CollectWatchItemsDependsOn Condition=\" '$(TargetFrameworks)' != '' AND '$(TargetFramework)' == '' \">\n      _CollectWatchItemsPerFramework;\n    </_CollectWatchItemsDependsOn>\n    <_CollectWatchItemsDependsOn Condition=\" '$(TargetFramework)' != '' \">\n      _CoreCollectWatchItems;\n    </_CollectWatchItemsDependsOn>\n  </PropertyGroup>\n\n  <Target Name=\"_CollectWatchItems\" DependsOnTargets=\"$(_CollectWatchItemsDependsOn)\" Returns=\"@(Watch)\" />\n\n  <Target Name=\"_CollectWatchItemsPerFramework\">\n    <ItemGroup>\n      <_TargetFramework Include=\"$(TargetFrameworks)\" />\n    </ItemGroup>\n\n    <MSBuild Projects=\"$(MSBuildProjectFullPath)\"\n             Targets=\"_CoreCollectWatchItems\"\n             Properties=\"TargetFramework=%(_TargetFramework.Identity)\">\n      <Output TaskParameter=\"TargetOutputs\" ItemName=\"Watch\" />\n    </MSBuild>\n  </Target>\n\n  <Target Name=\"_CoreCollectWatchItems\" Returns=\"@(Watch)\">\n    <!-- message used to debug -->\n    <Message Importance=\"High\" Text=\"Collecting watch items from '$(MSBuildProjectName)'\" Condition=\"'$(_DotNetWatchTraceOutput)'=='true'\" />\n\n    <Error Text=\"TargetFramework should be set\" Condition=\"'$(TargetFramework)' == '' \"/>\n\n    <ItemGroup>\n      <Watch Include=\"%(Compile.FullPath)\" Condition=\"'%(Compile.Watch)' != 'false'\" />\n      <Watch Include=\"%(EmbeddedResource.FullPath)\" Condition=\"'%(EmbeddedResource.Watch)' != 'false'\"/>\n      <Watch Include=\"$(MSBuildProjectFullPath)\" />\n      <_WatchProjects Include=\"%(ProjectReference.Identity)\" Condition=\"'%(ProjectReference.Watch)' != 'false'\" />\n    </ItemGroup>\n\n    <MSBuild Projects=\"@(_WatchProjects)\"\n             Targets=\"_CollectWatchItems\"\n             BuildInParallel=\"true\">\n      <Output TaskParameter=\"TargetOutputs\" ItemName=\"Watch\" />\n    </MSBuild>\n  </Target>\n\n</Project>\n"
  },
  {
    "path": "src/dotnet-watch/dotnet-watch.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n    <OutputType>exe</OutputType>\n    <Description>Command line tool to watch for source file changes during development and restart the dotnet command.</Description>\n    <RootNamespace>Microsoft.DotNet.Watcher.Tools</RootNamespace>\n    <PackageTags>dotnet;watch</PackageTags>\n    <PackAsTool>true</PackAsTool>\n    <!-- This is a requirement for Microsoft tool packages only. -->\n    <PackAsToolShimRuntimeIdentifiers>win-x64;win-x86</PackAsToolShimRuntimeIdentifiers>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Compile Include=\"..\\..\\shared\\**\\*.cs\" />\n    <None Include=\"assets\\**\\*\" CopyToOutputDirectory=\"PreserveNewest\" CopyToPublishDirectory=\"PreserveNewest\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.Extensions.CommandLineUtils.Sources\" PrivateAssets=\"All\" Version=\"$(MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Process.Sources\" PrivateAssets=\"All\" Version=\"$(MicrosoftExtensionsProcessSourcesPackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "test/Directory.Build.props",
    "content": "<Project>\n  <Import Project=\"..\\Directory.Build.props\" />\n\n  <ItemGroup>\n    <PackageReference Include=\"Internal.AspNetCore.Sdk\" PrivateAssets=\"All\" Version=\"$(InternalAspNetCoreSdkPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Testing\" Version=\"$(MicrosoftAspNetCoreTestingPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.NET.Test.Sdk\" Version=\"$(MicrosoftNETTestSdkPackageVersion)\" />\n    <PackageReference Include=\"xunit\" Version=\"$(XunitPackageVersion)\" />\n    <PackageReference Include=\"xunit.runner.visualstudio\" Version=\"$(XunitRunnerVisualStudioPackageVersion)\" />\n  </ItemGroup>\n</Project>\n"
  },
  {
    "path": "test/Microsoft.HttpRepl.Tests/JsonVisitorTests.cs",
    "content": "using Microsoft.HttpRepl.Formatting;\nusing Microsoft.HttpRepl.Preferences;\nusing Microsoft.Repl.ConsoleHandling;\nusing Xunit;\n\nnamespace Microsoft.HttpRepl.Tests\n{\n    public class JsonVisitorTests\n    {\n        [Fact]\n        public void JsonVisitor_ObjectWithComments()\n        {\n            string testData = @\"[\n    {\n        //Object 1\n        \"\"property\"\": \"\"value\"\",\n        \"\"and\"\": \"\"again\"\"\n    },\n    {\n        //Object 2\n    },\n    [\n        //An array\n    ],\n    null,\n    1,\n    3.2,\n    \"\"test\"\",\n    false\n]\";\n\n            string formatted = JsonVisitor.FormatAndColorize(new MockJsonConfig(), testData);\n        }\n\n        private class MockJsonConfig : IJsonConfig\n        {\n            public int IndentSize => 2;\n\n            public AllowedColors DefaultColor => AllowedColors.None;\n\n            public AllowedColors ArrayBraceColor => AllowedColors.None;\n\n            public AllowedColors ObjectBraceColor => AllowedColors.None;\n\n            public AllowedColors CommaColor => AllowedColors.None;\n\n            public AllowedColors NameColor => AllowedColors.None;\n\n            public AllowedColors NameSeparatorColor => AllowedColors.None;\n\n            public AllowedColors BoolColor => AllowedColors.None;\n\n            public AllowedColors NumericColor => AllowedColors.None;\n\n            public AllowedColors StringColor => AllowedColors.None;\n\n            public AllowedColors NullColor => AllowedColors.None;\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n\n    <IsPackable>false</IsPackable>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Newtonsoft.Json\" Version=\"$(NewtonsoftJsonPackageVersion)\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.HttpRepl\\Microsoft.HttpRepl.csproj\" />\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.Repl\\Microsoft.Repl.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "test/Microsoft.Repl.Tests/Microsoft.Repl.Tests.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.Repl\\Microsoft.Repl.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "test/Microsoft.Repl.Tests/ParserTests.cs",
    "content": "using Microsoft.Repl.Parsing;\nusing Xunit;\n\nnamespace Microsoft.Repl.Tests\n{\n    public class ParserTests\n    {\n        [Fact]\n        public void ParserTests_Basic()\n        {\n            string testString = \"\\\"this is a test\\\" of \\\"Escape\\\\\\\\Sequences\\\\\\\"\\\"\";\n\n            CoreParser parser = new CoreParser();\n            ICoreParseResult result = parser.Parse(testString, 29);\n\n            Assert.Equal(3, result.Sections.Count);\n            Assert.Equal(2, result.SelectedSection);\n            Assert.Equal(0, result.SectionStartLookup[0]);\n            Assert.Equal(17, result.SectionStartLookup[1]);\n            Assert.Equal(20, result.SectionStartLookup[2]);\n            Assert.Equal(7, result.CaretPositionWithinSelectedSection);\n            Assert.Equal(29, result.CaretPositionWithinCommandText);\n            Assert.Equal(testString, result.CommandText);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Shared/TestConsole.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Threading.Tasks;\nusing System.Text;\nusing Xunit.Abstractions;\n\nnamespace Microsoft.Extensions.Tools.Internal\n{\n    public class TestConsole : IConsole\n    {\n        private event ConsoleCancelEventHandler _cancelKeyPress;\n        private readonly TaskCompletionSource<bool> _cancelKeySubscribed = new TaskCompletionSource<bool>();\n\n        public TestConsole(ITestOutputHelper output)\n        {\n            var writer = new TestOutputWriter(output);\n            Error = writer;\n            Out = writer;\n        }\n\n        public event ConsoleCancelEventHandler CancelKeyPress\n        {\n            add\n            {\n                _cancelKeyPress += value;\n                _cancelKeySubscribed.TrySetResult(true);\n            }\n            remove => _cancelKeyPress -= value;\n        }\n\n        public Task CancelKeyPressSubscribed => _cancelKeySubscribed.Task;\n\n        public TextWriter Error { get; set; }\n        public TextWriter Out { get; set; }\n        public TextReader In { get; set; } = new StringReader(string.Empty);\n        public bool IsInputRedirected { get; set; } = false;\n        public bool IsOutputRedirected { get; } = false;\n        public bool IsErrorRedirected { get; } = false;\n        public ConsoleColor ForegroundColor { get; set; }\n\n        public ConsoleCancelEventArgs ConsoleCancelKey()\n        {\n            var ctor = typeof(ConsoleCancelEventArgs)\n                .GetTypeInfo()\n                .DeclaredConstructors\n                .Single(c => c.GetParameters().First().ParameterType == typeof(ConsoleSpecialKey));\n            var args = (ConsoleCancelEventArgs)ctor.Invoke(new object[] { ConsoleSpecialKey.ControlC });\n            _cancelKeyPress.Invoke(this, args);\n            return args;\n        }\n\n        public void ResetColor()\n        {\n        }\n\n        private class TestOutputWriter : TextWriter\n        {\n            private readonly ITestOutputHelper _output;\n            private readonly StringBuilder _sb = new StringBuilder();\n\n            public TestOutputWriter(ITestOutputHelper output)\n            {\n                _output = output;\n            }\n\n            public override Encoding Encoding => Encoding.Unicode;\n\n            public override void Write(char value)\n            {\n                if (value == '\\r' || value == '\\n')\n                {\n                    if (_sb.Length > 0)\n                    {\n                        _output.WriteLine(_sb.ToString());\n                        _sb.Clear();\n                    }\n                }\n                else\n                {\n                    _sb.Append(value);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/Shared/TestReporter.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Xunit.Abstractions;\n\nnamespace Microsoft.Extensions.Tools.Internal\n{\n    public class TestReporter : IReporter\n    {\n        private readonly ITestOutputHelper _output;\n\n        public TestReporter(ITestOutputHelper output)\n        {\n            _output = output;\n        }\n\n        public void Verbose(string message)\n        {\n            _output.WriteLine(\"verbose: \" + message);\n        }\n\n        public void Output(string message)\n        {\n            _output.WriteLine(\"output: \" + message);\n        }\n\n        public void Warn(string message)\n        {\n            _output.WriteLine(\"warn: \" + message);\n        }\n\n        public void Error(string message)\n        {\n            _output.WriteLine(\"error: \" + message);\n        }\n    }\n}"
  },
  {
    "path": "test/dotnet-user-secrets.Tests/InitCommandTest.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Text;\nusing Microsoft.Extensions.Configuration.UserSecrets.Tests;\nusing Microsoft.Extensions.SecretManager.Tools.Internal;\nusing Microsoft.Extensions.Tools.Internal;\nusing Xunit;\nusing Xunit.Abstractions;\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Tests\n{\n    public class InitCommandTests : IClassFixture<UserSecretsTestFixture>\n    {\n        private UserSecretsTestFixture _fixture;\n        private ITestOutputHelper _output;\n        private TestConsole _console;\n        private StringBuilder _textOutput;\n\n        public InitCommandTests(UserSecretsTestFixture fixture, ITestOutputHelper output)\n        {\n            _fixture = fixture;\n            _output = output;\n            _textOutput = new StringBuilder();\n\n            _console = new TestConsole(output)\n            {\n                Error = new StringWriter(_textOutput),\n                Out = new StringWriter(_textOutput),\n            };\n        }\n\n        private CommandContext MakeCommandContext() => new CommandContext(null, new TestReporter(_output), _console);\n\n        [Fact]\n        public void AddsSecretIdToProject()\n        {\n            var projectDir = _fixture.CreateProject(null);\n\n            new InitCommand(null, null).Execute(MakeCommandContext(), projectDir);\n\n            var idResolver = new ProjectIdResolver(MakeCommandContext().Reporter, projectDir);\n\n            Assert.False(string.IsNullOrWhiteSpace(idResolver.Resolve(null, null)));\n        }\n\n        [Fact]\n        public void AddsSpecificSecretIdToProject()\n        {\n            const string SecretId = \"TestSecretId\";\n\n            var projectDir = _fixture.CreateProject(null);\n\n            new InitCommand(SecretId, null).Execute(MakeCommandContext(), projectDir);\n\n            var idResolver = new ProjectIdResolver(MakeCommandContext().Reporter, projectDir);\n\n            Assert.Equal(SecretId, idResolver.Resolve(null, null));\n        }\n\n        [Fact]\n        public void AddsEscapedSpecificSecretIdToProject()\n        {\n            const string SecretId = @\"<lots of XML invalid values>&\";\n\n            var projectDir = _fixture.CreateProject(null);\n\n            new InitCommand(SecretId, null).Execute(MakeCommandContext(), projectDir);\n\n            var idResolver = new ProjectIdResolver(MakeCommandContext().Reporter, projectDir);\n\n            Assert.Equal(SecretId, idResolver.Resolve(null, null));\n        }\n\n        [Fact]\n        public void DoesNotGenerateIdForProjectWithSecretId()\n        {\n            const string SecretId = \"AlreadyExists\";\n\n            var projectDir = _fixture.CreateProject(SecretId);\n\n            new InitCommand(null, null).Execute(MakeCommandContext(), projectDir);\n\n            var idResolver = new ProjectIdResolver(MakeCommandContext().Reporter, projectDir);\n\n            Assert.Equal(SecretId, idResolver.Resolve(null, null));\n        }\n\n        [Fact]\n        public void OverridesIdForProjectWithSecretId()\n        {\n            const string SecretId = \"AlreadyExists\";\n            const string NewId = \"TestValue\";\n\n            var projectDir = _fixture.CreateProject(SecretId);\n\n            new InitCommand(NewId, null).Execute(MakeCommandContext(), projectDir);\n\n            var idResolver = new ProjectIdResolver(MakeCommandContext().Reporter, projectDir);\n\n            Assert.Equal(NewId, idResolver.Resolve(null, null));\n        }\n\n        [Fact]\n        public void FailsForInvalidId()\n        {\n            string secretId = $\"invalid{Path.GetInvalidPathChars()[0]}secret-id\";\n\n            var projectDir = _fixture.CreateProject(null);\n\n            Assert.Throws<ArgumentException>(() =>\n            {\n                new InitCommand(secretId, null).Execute(MakeCommandContext(), projectDir);\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-user-secrets.Tests/MsBuildProjectFinderTest.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.IO;\nusing Microsoft.Extensions.SecretManager.Tools.Internal;\nusing Xunit;\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Tests\n{\n    public class MsBuildProjectFinderTest\n    {\n        [Theory]\n        [InlineData(\".csproj\")]\n        [InlineData(\".vbproj\")]\n        [InlineData(\".fsproj\")]\n        public void FindsSingleProject(string extension)\n        {\n            using (var files = new TemporaryFileProvider())\n            {\n                var filename = \"TestProject\" + extension;\n                files.Add(filename, \"\");\n\n                var finder = new MsBuildProjectFinder(files.Root);\n\n                Assert.Equal(Path.Combine(files.Root, filename), finder.FindMsBuildProject(null));\n            }\n        }\n\n        [Fact]\n        public void ThrowsWhenNoFile()\n        {\n            using (var files = new TemporaryFileProvider())\n            {\n                var finder = new MsBuildProjectFinder(files.Root);\n\n                Assert.Throws<FileNotFoundException>(() => finder.FindMsBuildProject(null));\n            }\n        }\n\n        [Fact]\n        public void DoesNotMatchXproj()\n        {\n            using (var files = new TemporaryFileProvider())\n            {\n                var finder = new MsBuildProjectFinder(files.Root);\n                files.Add(\"test.xproj\", \"\");\n\n                Assert.Throws<FileNotFoundException>(() => finder.FindMsBuildProject(null));\n            }\n        }\n\n        [Fact]\n        public void ThrowsWhenMultipleFile()\n        {\n            using (var files = new TemporaryFileProvider())\n            {\n                files.Add(\"Test1.csproj\", \"\");\n                files.Add(\"Test2.csproj\", \"\");\n                var finder = new MsBuildProjectFinder(files.Root);\n\n                Assert.Throws<FileNotFoundException>(() => finder.FindMsBuildProject(null));\n            }\n        }\n\n        [Fact]\n        public void ThrowsWhenFileDoesNotExist()\n        {\n            using (var files = new TemporaryFileProvider())\n            {\n                var finder = new MsBuildProjectFinder(files.Root);\n\n                Assert.Throws<FileNotFoundException>(() => finder.FindMsBuildProject(\"test.csproj\"));\n            }\n        }\n\n        [Fact]\n        public void ThrowsWhenRootDoesNotExist()\n        {\n            var files = new TemporaryFileProvider();\n            var finder = new MsBuildProjectFinder(files.Root);\n            files.Dispose();\n            Assert.Throws<FileNotFoundException>(() => finder.FindMsBuildProject(null));\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-user-secrets.Tests/SecretManagerTests.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Text;\nusing Microsoft.Extensions.Configuration.UserSecrets;\nusing Microsoft.Extensions.Configuration.UserSecrets.Tests;\nusing Microsoft.Extensions.Tools.Internal;\nusing Xunit;\nusing Xunit.Abstractions;\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Tests\n{\n    public class SecretManagerTests : IClassFixture<UserSecretsTestFixture>\n    {\n        private readonly TestConsole _console;\n        private readonly UserSecretsTestFixture _fixture;\n        private readonly StringBuilder _output = new StringBuilder();\n\n        public SecretManagerTests(UserSecretsTestFixture fixture, ITestOutputHelper output)\n        {\n            _fixture = fixture;\n\n            _console = new TestConsole(output)\n            {\n                Error = new StringWriter(_output),\n                Out = new StringWriter(_output),\n            };\n        }\n\n        private Program CreateProgram()\n        {\n            return new Program(_console, Directory.GetCurrentDirectory());\n        }\n\n        [Theory]\n        [InlineData(null)]\n        [InlineData(\"\")]\n        public void Error_MissingId(string id)\n        {\n            var project = Path.Combine(_fixture.CreateProject(id), \"TestProject.csproj\");\n            var secretManager = CreateProgram();\n\n            secretManager.RunInternal(\"list\", \"-p\", project);\n            Assert.Contains(Resources.FormatError_ProjectMissingId(project), _output.ToString());\n        }\n\n        [Fact]\n        public void Error_InvalidProjectFormat()\n        {\n            var project = Path.Combine(_fixture.CreateProject(\"<\"), \"TestProject.csproj\");\n            var secretManager = CreateProgram();\n\n            secretManager.RunInternal(\"list\", \"-p\", project);\n            Assert.Contains(Resources.FormatError_ProjectFailedToLoad(project), _output.ToString());\n        }\n\n        [Fact]\n        public void Error_Project_DoesNotExist()\n        {\n            var projectPath = Path.Combine(_fixture.GetTempSecretProject(), \"does_not_exist\", \"TestProject.csproj\");\n            var secretManager = CreateProgram();\n\n            secretManager.RunInternal(\"list\", \"--project\", projectPath);\n            Assert.Contains(Resources.FormatError_ProjectPath_NotFound(projectPath), _output.ToString());\n        }\n\n        [Fact]\n        public void SupportsRelativePaths()\n        {\n            var projectPath = _fixture.GetTempSecretProject();\n            var cwd = Path.Combine(projectPath, \"nested1\");\n            Directory.CreateDirectory(cwd);\n            var secretManager = new Program(_console, cwd);\n\n            secretManager.RunInternal(\"list\", \"-p\", \"..\" + Path.DirectorySeparatorChar, \"--verbose\");\n\n            Assert.Contains(Resources.FormatMessage_Project_File_Path(Path.Combine(cwd, \"..\", \"TestProject.csproj\")), _output.ToString());\n        }\n\n        [Theory]\n        [InlineData(true)]\n        [InlineData(false)]\n        public void SetSecrets(bool fromCurrentDirectory)\n        {\n            var secrets = new KeyValuePair<string, string>[]\n                        {\n                            new KeyValuePair<string, string>(\"key1\", Guid.NewGuid().ToString()),\n                            new KeyValuePair<string, string>(\"Facebook:AppId\", Guid.NewGuid().ToString()),\n                            new KeyValuePair<string, string>(@\"key-@\\/.~123!#$%^&*())-+==\", @\"key-@\\/.~123!#$%^&*())-+==\"),\n                            new KeyValuePair<string, string>(\"key2\", string.Empty)\n                        };\n\n            var projectPath = _fixture.GetTempSecretProject();\n            var dir = fromCurrentDirectory\n                ? projectPath\n                : Path.GetTempPath();\n            var secretManager = new Program(_console, dir);\n\n            foreach (var secret in secrets)\n            {\n                var parameters = fromCurrentDirectory ?\n                    new string[] { \"set\", secret.Key, secret.Value } :\n                    new string[] { \"set\", secret.Key, secret.Value, \"-p\", projectPath };\n                secretManager.RunInternal(parameters);\n            }\n\n            foreach (var keyValue in secrets)\n            {\n                Assert.Contains(\n                    string.Format(\"Successfully saved {0} = {1} to the secret store.\", keyValue.Key, keyValue.Value),\n                    _output.ToString());\n            }\n\n            _output.Clear();\n            var args = fromCurrentDirectory\n                ? new string[] { \"list\" }\n                : new string[] { \"list\", \"-p\", projectPath };\n            secretManager.RunInternal(args);\n            foreach (var keyValue in secrets)\n            {\n                Assert.Contains(\n                    string.Format(\"{0} = {1}\", keyValue.Key, keyValue.Value),\n                    _output.ToString());\n            }\n\n            // Remove secrets.\n            _output.Clear();\n            foreach (var secret in secrets)\n            {\n                var parameters = fromCurrentDirectory ?\n                    new string[] { \"remove\", secret.Key } :\n                    new string[] { \"remove\", secret.Key, \"-p\", projectPath };\n                secretManager.RunInternal(parameters);\n            }\n\n            // Verify secrets are removed.\n            _output.Clear();\n            args = fromCurrentDirectory\n                ? new string[] { \"list\" }\n                : new string[] { \"list\", \"-p\", projectPath };\n            secretManager.RunInternal(args);\n            Assert.Contains(Resources.Error_No_Secrets_Found, _output.ToString());\n        }\n\n        [Fact]\n        public void SetSecret_Update_Existing_Secret()\n        {\n            var projectPath = _fixture.GetTempSecretProject();\n            var secretManager = CreateProgram();\n\n            secretManager.RunInternal(\"set\", \"secret1\", \"value1\", \"-p\", projectPath);\n            Assert.Contains(\"Successfully saved secret1 = value1 to the secret store.\", _output.ToString());\n            secretManager.RunInternal(\"set\", \"secret1\", \"value2\", \"-p\", projectPath);\n            Assert.Contains(\"Successfully saved secret1 = value2 to the secret store.\", _output.ToString());\n\n            _output.Clear();\n\n            secretManager.RunInternal(\"list\", \"-p\", projectPath);\n            Assert.Contains(\"secret1 = value2\", _output.ToString());\n        }\n\n        [Fact]\n        public void SetSecret_With_Verbose_Flag()\n        {\n            string secretId;\n            var projectPath = _fixture.GetTempSecretProject(out secretId);\n            var secretManager = CreateProgram();\n\n            secretManager.RunInternal(\"-v\", \"set\", \"secret1\", \"value1\", \"-p\", projectPath);\n            Assert.Contains(string.Format(\"Project file path {0}.\", Path.Combine(projectPath, \"TestProject.csproj\")), _output.ToString());\n            Assert.Contains(string.Format(\"Secrets file path {0}.\", PathHelper.GetSecretsPathFromSecretsId(secretId)), _output.ToString());\n            Assert.Contains(\"Successfully saved secret1 = value1 to the secret store.\", _output.ToString());\n            _output.Clear();\n\n            secretManager.RunInternal(\"-v\", \"list\", \"-p\", projectPath);\n\n            Assert.Contains(string.Format(\"Project file path {0}.\", Path.Combine(projectPath, \"TestProject.csproj\")), _output.ToString());\n            Assert.Contains(string.Format(\"Secrets file path {0}.\", PathHelper.GetSecretsPathFromSecretsId(secretId)), _output.ToString());\n            Assert.Contains(\"secret1 = value1\", _output.ToString());\n        }\n\n        [Fact]\n        public void Remove_Non_Existing_Secret()\n        {\n            var projectPath = _fixture.GetTempSecretProject();\n            var secretManager = CreateProgram();\n            secretManager.RunInternal(\"remove\", \"secret1\", \"-p\", projectPath);\n            Assert.Contains(\"Cannot find 'secret1' in the secret store.\", _output.ToString());\n        }\n\n        [Fact]\n        public void Remove_Is_Case_Insensitive()\n        {\n            var projectPath = _fixture.GetTempSecretProject();\n            var secretManager = CreateProgram();\n            secretManager.RunInternal(\"set\", \"SeCreT1\", \"value\", \"-p\", projectPath);\n            secretManager.RunInternal(\"list\", \"-p\", projectPath);\n            Assert.Contains(\"SeCreT1 = value\", _output.ToString());\n            secretManager.RunInternal(\"remove\", \"secret1\", \"-p\", projectPath);\n\n            _output.Clear();\n            secretManager.RunInternal(\"list\", \"-p\", projectPath);\n\n            Assert.Contains(Resources.Error_No_Secrets_Found, _output.ToString());\n        }\n\n        [Fact]\n        public void List_Flattens_Nested_Objects()\n        {\n            string secretId;\n            var projectPath = _fixture.GetTempSecretProject(out secretId);\n            var secretsFile = PathHelper.GetSecretsPathFromSecretsId(secretId);\n            Directory.CreateDirectory(Path.GetDirectoryName(secretsFile));\n            File.WriteAllText(secretsFile, @\"{ \"\"AzureAd\"\": { \"\"ClientSecret\"\": \"\"abcdéƒ©˙î\"\"} }\", Encoding.UTF8);\n            var secretManager = CreateProgram();\n            secretManager.RunInternal(\"list\", \"-p\", projectPath);\n            Assert.Contains(\"AzureAd:ClientSecret = abcdéƒ©˙î\", _output.ToString());\n        }\n\n        [Fact]\n        public void List_Json()\n        {\n            string id;\n            var projectPath = _fixture.GetTempSecretProject(out id);\n            var secretsFile = PathHelper.GetSecretsPathFromSecretsId(id);\n            Directory.CreateDirectory(Path.GetDirectoryName(secretsFile));\n            File.WriteAllText(secretsFile, @\"{ \"\"AzureAd\"\": { \"\"ClientSecret\"\": \"\"abcdéƒ©˙î\"\"} }\", Encoding.UTF8);\n            var secretManager = new Program(_console, Path.GetDirectoryName(projectPath));\n            secretManager.RunInternal(\"list\", \"--id\", id, \"--json\");\n            var stdout = _output.ToString();\n            Assert.Contains(\"//BEGIN\", stdout);\n            Assert.Contains(@\"\"\"AzureAd:ClientSecret\"\": \"\"abcdéƒ©˙î\"\"\", stdout);\n            Assert.Contains(\"//END\", stdout);\n        }\n\n        [Fact]\n        public void Set_Flattens_Nested_Objects()\n        {\n            string secretId;\n            var projectPath = _fixture.GetTempSecretProject(out secretId);\n            var secretsFile = PathHelper.GetSecretsPathFromSecretsId(secretId);\n            Directory.CreateDirectory(Path.GetDirectoryName(secretsFile));\n            File.WriteAllText(secretsFile, @\"{ \"\"AzureAd\"\": { \"\"ClientSecret\"\": \"\"abcdéƒ©˙î\"\"} }\", Encoding.UTF8);\n            var secretManager = CreateProgram();\n            secretManager.RunInternal(\"set\", \"AzureAd:ClientSecret\", \"¡™£¢∞\", \"-p\", projectPath);\n            secretManager.RunInternal(\"list\", \"-p\", projectPath);\n\n            Assert.Contains(\"AzureAd:ClientSecret = ¡™£¢∞\", _output.ToString());\n            var fileContents = File.ReadAllText(secretsFile, Encoding.UTF8);\n            Assert.Equal(@\"{\n    \"\"AzureAd:ClientSecret\"\": \"\"¡™£¢∞\"\"\n}\",\n                fileContents, ignoreLineEndingDifferences: true, ignoreWhiteSpaceDifferences: true);\n        }\n\n        [Fact]\n        public void List_Empty_Secrets_File()\n        {\n            var projectPath = _fixture.GetTempSecretProject();\n            var secretManager = CreateProgram();\n            secretManager.RunInternal(\"list\", \"-p\", projectPath);\n            Assert.Contains(Resources.Error_No_Secrets_Found, _output.ToString());\n        }\n\n        [Theory]\n        [InlineData(true)]\n        [InlineData(false)]\n        public void Clear_Secrets(bool fromCurrentDirectory)\n        {\n            var projectPath = _fixture.GetTempSecretProject();\n\n            var dir = fromCurrentDirectory\n                ? projectPath\n                : Path.GetTempPath();\n\n            var secretManager = new Program(_console, dir);\n\n            var secrets = new KeyValuePair<string, string>[]\n                        {\n                            new KeyValuePair<string, string>(\"key1\", Guid.NewGuid().ToString()),\n                            new KeyValuePair<string, string>(\"Facebook:AppId\", Guid.NewGuid().ToString()),\n                            new KeyValuePair<string, string>(@\"key-@\\/.~123!#$%^&*())-+==\", @\"key-@\\/.~123!#$%^&*())-+==\"),\n                            new KeyValuePair<string, string>(\"key2\", string.Empty)\n                        };\n\n            foreach (var secret in secrets)\n            {\n                var parameters = fromCurrentDirectory ?\n                    new string[] { \"set\", secret.Key, secret.Value } :\n                    new string[] { \"set\", secret.Key, secret.Value, \"-p\", projectPath };\n                secretManager.RunInternal(parameters);\n            }\n\n            foreach (var keyValue in secrets)\n            {\n                Assert.Contains(\n                    string.Format(\"Successfully saved {0} = {1} to the secret store.\", keyValue.Key, keyValue.Value),\n                    _output.ToString());\n            }\n\n            // Verify secrets are persisted.\n            _output.Clear();\n            var args = fromCurrentDirectory ?\n                new string[] { \"list\" } :\n                new string[] { \"list\", \"-p\", projectPath };\n            secretManager.RunInternal(args);\n            foreach (var keyValue in secrets)\n            {\n                Assert.Contains(\n                    string.Format(\"{0} = {1}\", keyValue.Key, keyValue.Value),\n                    _output.ToString());\n            }\n\n            // Clear secrets.\n            _output.Clear();\n            args = fromCurrentDirectory ? new string[] { \"clear\" } : new string[] { \"clear\", \"-p\", projectPath };\n            secretManager.RunInternal(args);\n\n            args = fromCurrentDirectory ? new string[] { \"list\" } : new string[] { \"list\", \"-p\", projectPath };\n            secretManager.RunInternal(args);\n            Assert.Contains(Resources.Error_No_Secrets_Found, _output.ToString());\n        }\n\n        [Fact]\n        public void Init_When_Project_Has_No_Secrets_Id()\n        {\n            var projectPath = _fixture.CreateProject(null);\n            var project = Path.Combine(projectPath, \"TestProject.csproj\");\n            var secretManager = new Program(_console, projectPath);\n\n            secretManager.RunInternal(\"init\", \"-p\", project);\n\n            Assert.DoesNotContain(Resources.FormatError_ProjectMissingId(project), _output.ToString());\n            Assert.DoesNotContain(\"--help\", _output.ToString());\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-user-secrets.Tests/SetCommandTest.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.IO;\nusing System.Collections.Generic;\nusing Microsoft.Extensions.SecretManager.Tools.Internal;\nusing Microsoft.Extensions.Tools.Internal;\nusing Xunit;\nusing Xunit.Abstractions;\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Tests\n{\n\n    public class SetCommandTest\n    {\n        private readonly ITestOutputHelper _output;\n\n        public SetCommandTest(ITestOutputHelper output)\n        {\n            _output = output;\n        }\n\n        [Fact]\n        public void SetsFromPipedInput()\n        {\n            var input = @\"\n{\n   \"\"Key1\"\": \"\"str value\"\",\n\"\"Key2\"\": 1234,\n\"\"Key3\"\": false\n}\";\n            var testConsole = new TestConsole(_output)\n            {\n                IsInputRedirected = true,\n                In = new StringReader(input)\n            };\n            var secretStore = new TestSecretsStore(_output);\n            var command = new SetCommand.FromStdInStrategy();\n\n            command.Execute(new CommandContext(secretStore, new TestReporter(_output), testConsole));\n\n            Assert.Equal(3, secretStore.Count);\n            Assert.Equal(\"str value\", secretStore[\"Key1\"]);\n            Assert.Equal(\"1234\", secretStore[\"Key2\"]);\n            Assert.Equal(\"False\", secretStore[\"Key3\"]);\n        }\n\n        [Fact]\n        public void ParsesNestedObjects()\n        {\n            var input = @\"\n                {\n                   \"\"Key1\"\": {\n                       \"\"nested\"\" : \"\"value\"\"\n                   },\n                   \"\"array\"\": [ 1, 2 ]\n                }\";\n\n            var testConsole = new TestConsole(_output)\n            {\n                IsInputRedirected = true,\n                In = new StringReader(input)\n            };\n            var secretStore = new TestSecretsStore(_output);\n            var command = new SetCommand.FromStdInStrategy();\n\n            command.Execute(new CommandContext(secretStore, new TestReporter(_output), testConsole));\n\n            Assert.Equal(3, secretStore.Count);\n            Assert.True(secretStore.ContainsKey(\"Key1:nested\"));\n            Assert.Equal(\"value\", secretStore[\"Key1:nested\"]);\n            Assert.Equal(\"1\", secretStore[\"array:0\"]);\n            Assert.Equal(\"2\", secretStore[\"array:1\"]);\n        }\n\n        [Fact]\n        public void OnlyPipesInIfNoArgs()\n        {\n            var testConsole = new TestConsole(_output)\n            {\n                IsInputRedirected = true,\n                In = new StringReader(\"\")\n            };\n            var options = CommandLineOptions.Parse(new [] { \"set\", \"key\", \"value\" }, testConsole);\n            Assert.IsType<SetCommand.ForOneValueStrategy>(options.Command);\n        }\n\n        private class TestSecretsStore : SecretsStore\n        {\n            public TestSecretsStore(ITestOutputHelper output)\n                : base(\"xyz\", new TestReporter(output))\n            {\n            }\n\n            protected override IDictionary<string, string> Load(string userSecretsId)\n            {\n                return new Dictionary<string, string>();\n            }\n\n            public override void Save()\n            {\n                // noop\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-user-secrets.Tests/TemporaryFileProvider.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Text;\n\nnamespace Microsoft.Extensions.SecretManager.Tools.Tests\n{\n    internal class TemporaryFileProvider : IDisposable\n    {\n        public TemporaryFileProvider()\n        {\n            Root = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), \"tmpfiles\", Guid.NewGuid().ToString())).FullName;\n        }\n\n        public string Root { get; }\n\n        public void Add(string filename, string contents)\n        {\n            File.WriteAllText(Path.Combine(Root, filename), contents, Encoding.UTF8);\n        }\n\n        public void Dispose()\n        {\n            Directory.Delete(Root, recursive: true);\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-user-secrets.Tests/UserSecretsTestFixture.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\n\nnamespace Microsoft.Extensions.Configuration.UserSecrets.Tests\n{\n    public class UserSecretsTestFixture : IDisposable\n    {\n        private Stack<Action> _disposables = new Stack<Action>();\n\n        public const string TestSecretsId = \"b918174fa80346bbb7f4a386729c0eff\";\n\n        public UserSecretsTestFixture()\n        {\n            _disposables.Push(() => TryDelete(Path.GetDirectoryName(PathHelper.GetSecretsPathFromSecretsId(TestSecretsId))));\n        }\n\n        public void Dispose()\n        {\n            while (_disposables.Count > 0)\n            {\n                _disposables.Pop()?.Invoke();\n            }\n        }\n\n        public string GetTempSecretProject()\n        {\n            string userSecretsId;\n            return GetTempSecretProject(out userSecretsId);\n        }\n\n        private const string ProjectTemplate = @\"<Project ToolsVersion=\"\"15.0\"\" Sdk=\"\"Microsoft.NET.Sdk\"\">\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFrameworks>netcoreapp3.0</TargetFrameworks>\n    {0}\n    <EnableDefaultCompileItems>false</EnableDefaultCompileItems>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Compile Include=\"\"**\\*.cs\"\" Exclude=\"\"Excluded.cs;$(DefaultItemExcludes)\"\" />\n  </ItemGroup>\n</Project>\";\n\n        public string GetTempSecretProject(out string userSecretsId)\n        {\n            userSecretsId = Guid.NewGuid().ToString();\n            return CreateProject(userSecretsId);\n        }\n\n        public string CreateProject(string userSecretsId)\n        {\n            var projectPath = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), \"usersecretstest\", Guid.NewGuid().ToString()));\n            var prop = string.IsNullOrEmpty(userSecretsId)\n                ? string.Empty\n                : $\"<UserSecretsId>{userSecretsId}</UserSecretsId>\";\n\n            File.WriteAllText(\n                Path.Combine(projectPath.FullName, \"TestProject.csproj\"),\n                string.Format(ProjectTemplate, prop));\n\n            var id = userSecretsId;\n            _disposables.Push(() =>\n            {\n                try\n                {\n                    // may throw if id is bad\n                    var secretsDir = Path.GetDirectoryName(PathHelper.GetSecretsPathFromSecretsId(id));\n                    TryDelete(secretsDir);\n                }\n                catch { }\n            });\n            _disposables.Push(() => TryDelete(projectPath.FullName));\n\n            return projectPath.FullName;\n        }\n\n        private static void TryDelete(string directory)\n        {\n            try\n            {\n                if (Directory.Exists(directory))\n                {\n                    Directory.Delete(directory, true);\n                }\n            }\n            catch (Exception)\n            {\n                // Ignore failures.\n                Console.WriteLine(\"Failed to delete \" + directory);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n    <AssemblyName>Microsoft.Extensions.SecretManager.Tools.Tests</AssemblyName>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Compile Include=\"..\\Shared\\**\\*.cs\" />\n    <Content Include=\"..\\..\\src\\dotnet-user-secrets\\assets\\SecretManager.targets\" Link=\"assets\\SecretManager.targets\" CopyToOutputDirectory=\"PreserveNewest\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\dotnet-user-secrets\\dotnet-user-secrets.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.Extensions.Configuration.UserSecrets\" Version=\"$(MicrosoftExtensionsConfigurationUserSecretsPackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Testing;\nusing Xunit;\nusing Xunit.Abstractions;\n\nnamespace Microsoft.DotNet.Watcher.Tools.FunctionalTests\n{\n    public class AppWithDepsTests : IDisposable\n    {\n        private readonly AppWithDeps _app;\n\n        public AppWithDepsTests(ITestOutputHelper logger)\n        {\n            _app = new AppWithDeps(logger);\n        }\n\n        [Fact]\n        public async Task ChangeFileInDependency()\n        {\n            await _app.StartWatcherAsync();\n\n            var fileToChange = Path.Combine(_app.DependencyFolder, \"Foo.cs\");\n            var programCs = File.ReadAllText(fileToChange);\n            File.WriteAllText(fileToChange, programCs);\n\n            await _app.HasRestarted();\n        }\n\n        public void Dispose()\n        {\n            _app.Dispose();\n        }\n\n        private class AppWithDeps : WatchableApp\n        {\n            private const string Dependency = \"Dependency\";\n\n            public AppWithDeps(ITestOutputHelper logger)\n                : base(\"AppWithDeps\", logger)\n            {\n                Scenario.AddTestProjectFolder(Dependency);\n\n                DependencyFolder = Path.Combine(Scenario.WorkFolder, Dependency);\n            }\n\n            public string DependencyFolder { get; private set; }\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/AwaitableProcess.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing System.Threading.Tasks.Dataflow;\nusing Microsoft.Extensions.Internal;\nusing Microsoft.Extensions.CommandLineUtils;\nusing Xunit.Abstractions;\n\nnamespace Microsoft.DotNet.Watcher.Tools.FunctionalTests\n{\n    public class AwaitableProcess : IDisposable\n    {\n        private Process _process;\n        private readonly ProcessSpec _spec;\n        private readonly List<string> _lines;\n        private BufferBlock<string> _source;\n        private ITestOutputHelper _logger;\n        private TaskCompletionSource<int> _exited;\n\n        public AwaitableProcess(ProcessSpec spec, ITestOutputHelper logger)\n        {\n            _spec = spec;\n            _logger = logger;\n            _source = new BufferBlock<string>();\n            _lines = new List<string>();\n            _exited = new TaskCompletionSource<int>();\n        }\n\n        public IEnumerable<string> Output => _lines;\n\n        public Task Exited => _exited.Task;\n\n        public int Id => _process.Id;\n\n        public void Start()\n        {\n            if (_process != null)\n            {\n                throw new InvalidOperationException(\"Already started\");\n            }\n\n            _process = new Process\n            {\n                EnableRaisingEvents = true,\n                StartInfo = new ProcessStartInfo\n                {\n                    UseShellExecute = false,\n                    FileName = _spec.Executable,\n                    WorkingDirectory = _spec.WorkingDirectory,\n                    Arguments = ArgumentEscaper.EscapeAndConcatenate(_spec.Arguments),\n                    RedirectStandardOutput = true,\n                    RedirectStandardError = true,\n                    Environment =\n                    {\n                        [\"DOTNET_SKIP_FIRST_TIME_EXPERIENCE\"] = \"true\"\n                    }\n                }\n            };\n\n            foreach (var env in _spec.EnvironmentVariables)\n            {\n                _process.StartInfo.EnvironmentVariables[env.Key] = env.Value;\n            }\n\n            _process.OutputDataReceived += OnData;\n            _process.ErrorDataReceived += OnData;\n            _process.Exited += OnExit;\n\n            _process.Start();\n            _process.BeginErrorReadLine();\n            _process.BeginOutputReadLine();\n            _logger.WriteLine($\"{DateTime.Now}: process start: '{_process.StartInfo.FileName} {_process.StartInfo.Arguments}'\");\n        }\n\n        public async Task<string> GetOutputLineAsync(string message, TimeSpan timeout)\n        {\n            _logger.WriteLine($\"Waiting for output line [msg == '{message}']. Will wait for {timeout.TotalSeconds} sec.\");\n            var cts = new CancellationTokenSource();\n            cts.CancelAfter(timeout);\n            return await GetOutputLineAsync($\"[msg == '{message}']\", m => string.Equals(m, message, StringComparison.Ordinal), cts.Token);\n        }\n\n        public async Task<string> GetOutputLineStartsWithAsync(string message, TimeSpan timeout)\n        {\n            _logger.WriteLine($\"Waiting for output line [msg.StartsWith('{message}')]. Will wait for {timeout.TotalSeconds} sec.\");\n            var cts = new CancellationTokenSource();\n            cts.CancelAfter(timeout);\n            return await GetOutputLineAsync($\"[msg.StartsWith('{message}')]\", m => m != null && m.StartsWith(message, StringComparison.Ordinal), cts.Token);\n        }\n\n        private async Task<string> GetOutputLineAsync(string predicateName, Predicate<string> predicate, CancellationToken cancellationToken)\n        {\n            while (!_source.Completion.IsCompleted)\n            {\n                while (await _source.OutputAvailableAsync(cancellationToken))\n                {\n                    var next = await _source.ReceiveAsync(cancellationToken);\n                    _lines.Add(next);\n                    var match = predicate(next);\n                    _logger.WriteLine($\"{DateTime.Now}: recv: '{next}'. {(match ? \"Matches\" : \"Does not match\")} condition '{predicateName}'.\");\n                    if (match)\n                    {\n                        return next;\n                    }\n                }\n            }\n\n            return null;\n        }\n\n        public async Task<IList<string>> GetAllOutputLinesAsync(CancellationToken cancellationToken)\n        {\n            var lines = new List<string>();\n            while (!_source.Completion.IsCompleted)\n            {\n                while (await _source.OutputAvailableAsync(cancellationToken))\n                {\n                    var next = await _source.ReceiveAsync(cancellationToken);\n                    _logger.WriteLine($\"{DateTime.Now}: recv: '{next}'\");\n                    lines.Add(next);\n                }\n            }\n            return lines;\n        }\n\n        private void OnData(object sender, DataReceivedEventArgs args)\n        {\n            var line = args.Data ?? string.Empty;\n            _logger.WriteLine($\"{DateTime.Now}: post: '{line}'\");\n            _source.Post(line);\n        }\n\n        private void OnExit(object sender, EventArgs args)\n        {\n            // Wait to ensure the process has exited and all output consumed\n            _process.WaitForExit();\n            _source.Complete();\n            _exited.TrySetResult(_process.ExitCode);\n            _logger.WriteLine($\"Process {_process.Id} has exited\");\n        }\n\n        public void Dispose()\n        {\n            _source.Complete();\n\n            if (_process != null)\n            {\n                if (!_process.HasExited)\n                {\n                    _process.KillTree();\n                }\n\n                _process.ErrorDataReceived -= OnData;\n                _process.OutputDataReceived -= OnData;\n                _process.Exited -= OnExit;\n                _process.Dispose();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Globalization;\nusing System.Threading.Tasks;\nusing Xunit;\nusing Xunit.Abstractions;\n\nnamespace Microsoft.DotNet.Watcher.Tools.FunctionalTests\n{\n    public class DotNetWatcherTests : IDisposable\n    {\n        private readonly ITestOutputHelper _logger;\n        private readonly KitchenSinkApp _app;\n\n        public DotNetWatcherTests(ITestOutputHelper logger)\n        {\n            _logger = logger;\n            _app = new KitchenSinkApp(logger);\n        }\n\n        [Fact]\n        public async Task RunsWithDotnetWatchEnvVariable()\n        {\n            Assert.True(string.IsNullOrEmpty(Environment.GetEnvironmentVariable(\"DOTNET_WATCH\")), \"DOTNET_WATCH cannot be set already when this test is running\");\n\n            await _app.StartWatcherAsync();\n            const string messagePrefix = \"DOTNET_WATCH = \";\n            var message = await _app.Process.GetOutputLineStartsWithAsync(messagePrefix, TimeSpan.FromMinutes(2));\n            var envValue = message.Substring(messagePrefix.Length);\n            Assert.Equal(\"1\", envValue);\n        }\n\n        [Fact]\n        public async Task RunsWithIterationEnvVariable()\n        {\n            await _app.StartWatcherAsync();\n            var source = Path.Combine(_app.SourceDirectory, \"Program.cs\");\n            var contents = File.ReadAllText(source);\n            const string messagePrefix = \"DOTNET_WATCH_ITERATION = \";\n            for (var i = 1; i <= 3; i++)\n            {\n                var message = await _app.Process.GetOutputLineStartsWithAsync(messagePrefix, TimeSpan.FromMinutes(2));\n                var count = int.Parse(message.Substring(messagePrefix.Length), CultureInfo.InvariantCulture);\n                Assert.Equal(i, count);\n\n                await _app.IsWaitingForFileChange();\n\n                try\n                {\n                    File.SetLastWriteTime(source, DateTime.Now);\n                    await _app.HasRestarted();\n                }\n                catch (Exception ex)\n                {\n                    _logger.WriteLine(\"Retrying. First attempt to restart app failed: \" + ex.Message);\n\n                    // retry\n                    File.SetLastWriteTime(source, DateTime.Now);\n                    await _app.HasRestarted();\n                }\n            }\n        }\n\n        public void Dispose()\n        {\n            _app.Dispose();\n        }\n\n        private class KitchenSinkApp : WatchableApp\n        {\n            public KitchenSinkApp(ITestOutputHelper logger)\n                : base(\"KitchenSink\", logger)\n            {\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/FileWatcherTests.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Threading;\nusing Microsoft.DotNet.Watcher.Internal;\nusing Xunit;\nusing Xunit.Abstractions;\n\nnamespace Microsoft.DotNet.Watcher.Tools.FunctionalTests\n{\n    public class FileWatcherTests\n    {\n        public FileWatcherTests(ITestOutputHelper output)\n        {\n            _output = output;\n        }\n\n        private const int DefaultTimeout = 10 * 1000; // 10 sec\n        private readonly ITestOutputHelper _output;\n\n        [Theory]\n        [InlineData(true)]\n        [InlineData(false)]\n        public void NewFile(bool usePolling)\n        {\n            UsingTempDirectory(dir =>\n            {\n                using (var changedEv = new ManualResetEvent(false))\n                using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling))\n                {\n                    var filesChanged = new HashSet<string>();\n\n                    watcher.OnFileChange += (_, f) =>\n                    {\n                        filesChanged.Add(f);\n                        changedEv.Set();\n                    };\n                    watcher.EnableRaisingEvents = true;\n\n                    var testFileFullPath = Path.Combine(dir, \"foo\");\n                    File.WriteAllText(testFileFullPath, string.Empty);\n\n                    Assert.True(changedEv.WaitOne(DefaultTimeout));\n                    Assert.Equal(testFileFullPath, filesChanged.Single());\n                }\n            });\n        }\n\n        [Theory]\n        [InlineData(true)]\n        [InlineData(false)]\n        public void ChangeFile(bool usePolling)\n        {\n            UsingTempDirectory(dir =>\n            {\n                var testFileFullPath = Path.Combine(dir, \"foo\");\n                File.WriteAllText(testFileFullPath, string.Empty);\n\n                using (var changedEv = new ManualResetEvent(false))\n                using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling))\n                {\n                    var filesChanged = new HashSet<string>();\n\n                    EventHandler<string> handler = null;\n                    handler = (_, f) =>\n                    {\n                        watcher.EnableRaisingEvents = false;\n                        watcher.OnFileChange -= handler;\n\n                        filesChanged.Add(f);\n                        changedEv.Set();\n                    };\n\n                    watcher.OnFileChange += handler;\n                    watcher.EnableRaisingEvents = true;\n\n                    // On Unix the file write time is in 1s increments;\n                    // if we don't wait, there's a chance that the polling\n                    // watcher will not detect the change\n                    Thread.Sleep(1000);\n                    File.WriteAllText(testFileFullPath, string.Empty);\n\n                    Assert.True(changedEv.WaitOne(DefaultTimeout));\n                    Assert.Equal(testFileFullPath, filesChanged.Single());\n                }\n            });\n        }\n\n        [Theory]\n        [InlineData(true)]\n        [InlineData(false)]\n        public void MoveFile(bool usePolling)\n        {\n            UsingTempDirectory(dir =>\n            {\n                var srcFile = Path.Combine(dir, \"foo\");\n                var dstFile = Path.Combine(dir, \"foo2\");\n\n                File.WriteAllText(srcFile, string.Empty);\n\n                using (var changedEv = new ManualResetEvent(false))\n                using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling))\n                {\n                    var filesChanged = new HashSet<string>();\n\n                    EventHandler<string> handler = null;\n                    handler = (_, f) =>\n                    {\n                        filesChanged.Add(f);\n\n                        if (filesChanged.Count >= 2)\n                        {\n                            watcher.EnableRaisingEvents = false;\n                            watcher.OnFileChange -= handler;\n\n                            changedEv.Set();\n                        }\n                    };\n\n                    watcher.OnFileChange += handler;\n                    watcher.EnableRaisingEvents = true;\n\n                    File.Move(srcFile, dstFile);\n\n                    Assert.True(changedEv.WaitOne(DefaultTimeout));\n                    Assert.Contains(srcFile, filesChanged);\n                    Assert.Contains(dstFile, filesChanged);\n                }\n            });\n        }\n\n        [Fact]\n        public void FileInSubdirectory()\n        {\n            UsingTempDirectory(dir =>\n            {\n                var subdir = Path.Combine(dir, \"subdir\");\n                Directory.CreateDirectory(subdir);\n\n                var testFileFullPath = Path.Combine(subdir, \"foo\");\n                File.WriteAllText(testFileFullPath, string.Empty);\n\n                using (var changedEv = new ManualResetEvent(false))\n                using (var watcher = FileWatcherFactory.CreateWatcher(dir, true))\n                {\n                    var filesChanged = new HashSet<string>();\n\n                    EventHandler<string> handler = null;\n                    handler = (_, f) =>\n                    {\n                        filesChanged.Add(f);\n\n                        if (filesChanged.Count >= 2)\n                        {\n                            watcher.EnableRaisingEvents = false;\n                            watcher.OnFileChange -= handler;\n                            changedEv.Set();\n                        }\n                    };\n\n                    watcher.OnFileChange += handler;\n                    watcher.EnableRaisingEvents = true;\n\n                    // On Unix the file write time is in 1s increments;\n                    // if we don't wait, there's a chance that the polling\n                    // watcher will not detect the change\n                    Thread.Sleep(1000);\n                    File.WriteAllText(testFileFullPath, string.Empty);\n\n                    Assert.True(changedEv.WaitOne(DefaultTimeout));\n                    Assert.Contains(subdir, filesChanged);\n                    Assert.Contains(testFileFullPath, filesChanged);\n                }\n            });\n        }\n\n        [Theory]\n        [InlineData(true)]\n        [InlineData(false)]\n        public void NoNotificationIfDisabled(bool usePolling)\n        {\n            UsingTempDirectory(dir =>\n            {\n                using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling))\n                using (var changedEv = new ManualResetEvent(false))\n                {\n                    watcher.OnFileChange += (_, f) => changedEv.Set();\n\n                    // Disable\n                    watcher.EnableRaisingEvents = false;\n\n                    var testFileFullPath = Path.Combine(dir, \"foo\");\n\n                    // On Unix the file write time is in 1s increments;\n                    // if we don't wait, there's a chance that the polling\n                    // watcher will not detect the change\n                    Thread.Sleep(1000);\n                    File.WriteAllText(testFileFullPath, string.Empty);\n\n                    Assert.False(changedEv.WaitOne(DefaultTimeout / 2));\n                }\n            });\n        }\n\n        [Theory]\n        [InlineData(true)]\n        [InlineData(false)]\n        public void DisposedNoEvents(bool usePolling)\n        {\n            UsingTempDirectory(dir =>\n            {\n                using (var changedEv = new ManualResetEvent(false))\n                {\n                    using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling))\n                    {\n                        watcher.OnFileChange += (_, f) => changedEv.Set();\n                        watcher.EnableRaisingEvents = true;\n                    }\n\n                    var testFileFullPath = Path.Combine(dir, \"foo\");\n\n                    // On Unix the file write time is in 1s increments;\n                    // if we don't wait, there's a chance that the polling\n                    // watcher will not detect the change\n                    Thread.Sleep(1000);\n                    File.WriteAllText(testFileFullPath, string.Empty);\n\n                    Assert.False(changedEv.WaitOne(DefaultTimeout / 2));\n                }\n            });\n        }\n\n        [Theory]\n        [InlineData(true)]\n        [InlineData(false)]\n        public void MultipleFiles(bool usePolling)\n        {\n            UsingTempDirectory(dir =>\n            {\n                File.WriteAllText(Path.Combine(dir, \"foo1\"), string.Empty);\n                File.WriteAllText(Path.Combine(dir, \"foo2\"), string.Empty);\n                File.WriteAllText(Path.Combine(dir, \"foo3\"), string.Empty);\n                File.WriteAllText(Path.Combine(dir, \"foo4\"), string.Empty);\n                File.WriteAllText(Path.Combine(dir, \"foo4\"), string.Empty);\n\n                var testFileFullPath = Path.Combine(dir, \"foo3\");\n\n                using (var changedEv = new ManualResetEvent(false))\n                using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling))\n                {\n                    var filesChanged = new HashSet<string>();\n\n                    EventHandler<string> handler = null;\n                    handler = (_, f) =>\n                    {\n                        watcher.EnableRaisingEvents = false;\n                        watcher.OnFileChange -= handler;\n                        filesChanged.Add(f);\n                        changedEv.Set();\n                    };\n\n                    watcher.OnFileChange += handler;\n                    watcher.EnableRaisingEvents = true;\n\n                    // On Unix the file write time is in 1s increments;\n                    // if we don't wait, there's a chance that the polling\n                    // watcher will not detect the change\n                    Thread.Sleep(1000);\n\n                    File.WriteAllText(testFileFullPath, string.Empty);\n\n                    Assert.True(changedEv.WaitOne(DefaultTimeout));\n                    Assert.Equal(testFileFullPath, filesChanged.Single());\n                }\n            });\n        }\n\n        [Theory]\n        [InlineData(true)]\n        [InlineData(false)]\n        public void MultipleTriggers(bool usePolling)\n        {\n            var filesChanged = new HashSet<string>();\n\n            UsingTempDirectory(dir =>\n            {\n                using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling))\n                {\n                    watcher.EnableRaisingEvents = true;\n\n                    for (var i = 0; i < 5; i++)\n                    {\n                        AssertFileChangeRaisesEvent(dir, watcher);\n                    }\n\n                    watcher.EnableRaisingEvents = false;\n                }\n            });\n        }\n\n        private void AssertFileChangeRaisesEvent(string directory, IFileSystemWatcher watcher)\n        {\n            using (var semaphoreSlim = new SemaphoreSlim(0))\n            {\n                var expectedPath = Path.Combine(directory, Path.GetRandomFileName());\n                EventHandler<string> handler = (object _, string f) =>\n                {\n                    _output.WriteLine(\"File changed: \" + f);\n                    try\n                    {\n                        if (string.Equals(f, expectedPath, StringComparison.OrdinalIgnoreCase))\n                        {\n                            semaphoreSlim.Release();\n                        }\n                    }\n                    catch (ObjectDisposedException)\n                    {\n                        // There's a known race condition here:\n                        // even though we tell the watcher to stop raising events and we unsubscribe the handler\n                        // there might be in-flight events that will still process. Since we dispose the reset\n                        // event, this code will fail if the handler executes after Dispose happens.\n                    }\n                };\n\n                File.AppendAllText(expectedPath, \" \");\n\n                watcher.OnFileChange += handler;\n                try\n                {\n                    // On Unix the file write time is in 1s increments;\n                    // if we don't wait, there's a chance that the polling\n                    // watcher will not detect the change\n                    Thread.Sleep(1000);\n                    File.AppendAllText(expectedPath, \" \");\n                    Assert.True(semaphoreSlim.Wait(DefaultTimeout), \"Expected a file change event for \" + expectedPath);\n                }\n                finally\n                {\n                    watcher.OnFileChange -= handler;\n                }\n            }\n        }\n\n        [Theory]\n        [InlineData(true)]\n        [InlineData(false)]\n        public void DeleteSubfolder(bool usePolling)\n        {\n            UsingTempDirectory(dir =>\n            {\n                var subdir = Path.Combine(dir, \"subdir\");\n                Directory.CreateDirectory(subdir);\n\n                var f1 = Path.Combine(subdir, \"foo1\");\n                var f2 = Path.Combine(subdir, \"foo2\");\n                var f3 = Path.Combine(subdir, \"foo3\");\n\n                File.WriteAllText(f1, string.Empty);\n                File.WriteAllText(f2, string.Empty);\n                File.WriteAllText(f3, string.Empty);\n\n                using (var changedEv = new AutoResetEvent(false))\n                using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling))\n                {\n                    var filesChanged = new HashSet<string>();\n\n                    EventHandler<string> handler = null;\n                    handler = (_, f) =>\n                    {\n                        filesChanged.Add(f);\n\n                        if (filesChanged.Count >= 4)\n                        {\n                            watcher.EnableRaisingEvents = false;\n                            watcher.OnFileChange -= handler;\n                            changedEv.Set();\n                        }\n                    };\n\n                    watcher.OnFileChange += handler;\n                    watcher.EnableRaisingEvents = true;\n\n                    Directory.Delete(subdir, recursive: true);\n\n                    Assert.True(changedEv.WaitOne(DefaultTimeout));\n\n                    Assert.Contains(f1, filesChanged);\n                    Assert.Contains(f2, filesChanged);\n                    Assert.Contains(f3, filesChanged);\n                    Assert.Contains(subdir, filesChanged);\n                }\n            });\n        }\n\n        private static void UsingTempDirectory(Action<string> action)\n        {\n            var tempFolder = Path.Combine(Path.GetTempPath(), $\"{nameof(FileWatcherTests)}-{Guid.NewGuid().ToString(\"N\")}\");\n            if (Directory.Exists(tempFolder))\n            {\n                Directory.Delete(tempFolder, recursive: true);\n            }\n\n            Directory.CreateDirectory(tempFolder);\n\n            try\n            {\n                action(tempFolder);\n            }\n            finally\n            {\n                Directory.Delete(tempFolder, recursive: true);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.DotNet.Watcher.Tools.Tests;\nusing Xunit;\nusing Xunit.Abstractions;\n\nnamespace Microsoft.DotNet.Watcher.Tools.FunctionalTests\n{\n    public class GlobbingAppTests : IDisposable\n    {\n        private GlobbingApp _app;\n        public GlobbingAppTests(ITestOutputHelper logger)\n        {\n            _app = new GlobbingApp(logger);\n        }\n\n        [Theory]\n        [InlineData(true)]\n        [InlineData(false)]\n        public async Task ChangeCompiledFile(bool usePollingWatcher)\n        {\n            _app.UsePollingWatcher = usePollingWatcher;\n            await _app.StartWatcherAsync();\n\n            var types = await _app.GetCompiledAppDefinedTypes();\n            Assert.Equal(2, types);\n\n            var fileToChange = Path.Combine(_app.SourceDirectory, \"include\", \"Foo.cs\");\n            var programCs = File.ReadAllText(fileToChange);\n            File.WriteAllText(fileToChange, programCs);\n\n            await _app.HasRestarted();\n            types = await _app.GetCompiledAppDefinedTypes();\n            Assert.Equal(2, types);\n        }\n\n        [Fact]\n        public async Task DeleteCompiledFile()\n        {\n            await _app.StartWatcherAsync();\n\n            var types = await _app.GetCompiledAppDefinedTypes();\n            Assert.Equal(2, types);\n\n            var fileToChange = Path.Combine(_app.SourceDirectory, \"include\", \"Foo.cs\");\n            File.Delete(fileToChange);\n\n            await _app.HasRestarted();\n            types = await _app.GetCompiledAppDefinedTypes();\n            Assert.Equal(1, types);\n        }\n\n        [Fact]\n        public async Task DeleteSourceFolder()\n        {\n            await _app.StartWatcherAsync();\n\n            var types = await _app.GetCompiledAppDefinedTypes();\n            Assert.Equal(2, types);\n\n            var folderToDelete = Path.Combine(_app.SourceDirectory, \"include\");\n            Directory.Delete(folderToDelete, recursive: true);\n\n            await _app.HasRestarted();\n            types = await _app.GetCompiledAppDefinedTypes();\n            Assert.Equal(1, types);\n        }\n\n        [Fact]\n        public async Task RenameCompiledFile()\n        {\n            await _app.StartWatcherAsync();\n\n            var oldFile = Path.Combine(_app.SourceDirectory, \"include\", \"Foo.cs\");\n            var newFile = Path.Combine(_app.SourceDirectory, \"include\", \"Foo_new.cs\");\n            File.Move(oldFile, newFile);\n\n            await _app.HasRestarted();\n        }\n\n        [Fact]\n        public async Task ChangeExcludedFile()\n        {\n            await _app.StartWatcherAsync();\n\n            var changedFile = Path.Combine(_app.SourceDirectory, \"exclude\", \"Baz.cs\");\n            File.WriteAllText(changedFile, \"\");\n\n            var restart = _app.HasRestarted();\n            var finished = await Task.WhenAny(Task.Delay(TimeSpan.FromSeconds(10)), restart);\n            Assert.NotSame(restart, finished);\n        }\n\n        [Fact]\n        public async Task ListsFiles()\n        {\n            await _app.PrepareAsync();\n            _app.Start(new [] { \"--list\" });\n            var cts = new CancellationTokenSource();\n            cts.CancelAfter(TimeSpan.FromSeconds(30));\n            var lines = await _app.Process.GetAllOutputLinesAsync(cts.Token);\n            var files = lines.Where(l => !l.StartsWith(\"watch :\"));\n\n            AssertEx.EqualFileList(\n                _app.Scenario.WorkFolder,\n                new[]\n                {\n                    \"GlobbingApp/Program.cs\",\n                    \"GlobbingApp/include/Foo.cs\",\n                    \"GlobbingApp/GlobbingApp.csproj\",\n                },\n                files);\n        }\n\n        public void Dispose()\n        {\n            _app.Dispose();\n        }\n\n        private class GlobbingApp : WatchableApp\n        {\n            public GlobbingApp(ITestOutputHelper logger)\n                : base(\"GlobbingApp\", logger)\n            {\n            }\n\n            public async Task<int> GetCompiledAppDefinedTypes()\n            {\n                var definedTypesMessage = await Process.GetOutputLineStartsWithAsync(\"Defined types = \", TimeSpan.FromSeconds(30));\n                return int.Parse(definedTypesMessage.Split('=').Last());\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Threading.Tasks;\nusing Xunit;\nusing Xunit.Abstractions;\n\nnamespace Microsoft.DotNet.Watcher.Tools.FunctionalTests\n{\n    public class NoDepsAppTests : IDisposable\n    {\n        private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30);\n\n        private readonly WatchableApp _app;\n        private readonly ITestOutputHelper _output;\n\n        public NoDepsAppTests(ITestOutputHelper logger)\n        {\n            _app = new WatchableApp(\"NoDepsApp\", logger);\n            _output = logger;\n        }\n\n        [Fact]\n        public async Task RestartProcessOnFileChange()\n        {\n            await _app.StartWatcherAsync(new[] { \"--no-exit\" });\n            var processIdentifier = await _app.GetProcessIdentifier();\n\n            // Then wait for it to restart when we change a file\n            var fileToChange = Path.Combine(_app.SourceDirectory, \"Program.cs\");\n            var programCs = File.ReadAllText(fileToChange);\n            File.WriteAllText(fileToChange, programCs);\n\n            await _app.HasRestarted();\n            Assert.DoesNotContain(_app.Process.Output, l => l.StartsWith(\"Exited with error code\"));\n\n            var processIdentifier2 = await _app.GetProcessIdentifier();\n            Assert.NotEqual(processIdentifier, processIdentifier2);\n        }\n\n        [Fact]\n        public async Task RestartProcessThatTerminatesAfterFileChange()\n        {\n            await _app.StartWatcherAsync();\n            var processIdentifier = await _app.GetProcessIdentifier();\n            await _app.HasExited(); // process should exit after run\n            await _app.IsWaitingForFileChange();\n\n            var fileToChange = Path.Combine(_app.SourceDirectory, \"Program.cs\");\n\n            try\n            {\n                File.SetLastWriteTime(fileToChange, DateTime.Now);\n                await _app.HasRestarted();\n            }\n            catch\n            {\n                // retry\n                File.SetLastWriteTime(fileToChange, DateTime.Now);\n                await _app.HasRestarted();\n            }\n\n            var processIdentifier2 = await _app.GetProcessIdentifier();\n            Assert.NotEqual(processIdentifier, processIdentifier2);\n            await _app.HasExited(); // process should exit after run\n        }\n\n        public void Dispose()\n        {\n            _app.Dispose();\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing System.Xml.Linq;\nusing Microsoft.Extensions.CommandLineUtils;\nusing Microsoft.Extensions.Internal;\nusing Xunit.Abstractions;\n\nnamespace Microsoft.DotNet.Watcher.Tools.FunctionalTests\n{\n    public class ProjectToolScenario : IDisposable\n    {\n        private static readonly string TestProjectSourceRoot = Path.Combine(AppContext.BaseDirectory, \"TestProjects\");\n        private readonly ITestOutputHelper _logger;\n\n        public ProjectToolScenario()\n            : this(null)\n        {\n        }\n\n        public ProjectToolScenario(ITestOutputHelper logger)\n        {\n            WorkFolder = Path.Combine(AppContext.BaseDirectory, \"tmp\", Path.GetRandomFileName());\n            DotNetWatchPath = Path.Combine(AppContext.BaseDirectory, \"tool\", \"dotnet-watch.dll\");\n\n            _logger = logger;\n            _logger?.WriteLine($\"The temporary test folder is {WorkFolder}\");\n\n            CreateTestDirectory();\n        }\n\n        public string WorkFolder { get; }\n\n        public string DotNetWatchPath { get; }\n\n        public void AddTestProjectFolder(string projectName)\n        {\n            var srcFolder = Path.Combine(TestProjectSourceRoot, projectName);\n            var destinationFolder = Path.Combine(WorkFolder, Path.GetFileName(projectName));\n            _logger?.WriteLine($\"Copying project {srcFolder} to {destinationFolder}\");\n\n            Directory.CreateDirectory(destinationFolder);\n\n            foreach (var directory in Directory.GetDirectories(srcFolder, \"*\", SearchOption.AllDirectories))\n            {\n                Directory.CreateDirectory(directory.Replace(srcFolder, destinationFolder));\n            }\n\n            foreach (var file in Directory.GetFiles(srcFolder, \"*\", SearchOption.AllDirectories))\n            {\n                File.Copy(file, file.Replace(srcFolder, destinationFolder), true);\n            }\n        }\n\n        public Task RestoreAsync(string project)\n        {\n            _logger?.WriteLine($\"Restoring msbuild project in {project}\");\n            return ExecuteCommandAsync(project, TimeSpan.FromSeconds(120), \"restore\");\n        }\n\n        public Task BuildAsync(string project)\n        {\n            _logger?.WriteLine($\"Building {project}\");\n            return ExecuteCommandAsync(project, TimeSpan.FromSeconds(60), \"build\");\n        }\n\n        private async Task ExecuteCommandAsync(string project, TimeSpan timeout, params string[] arguments)\n        {\n            var tcs = new TaskCompletionSource<object>();\n            project = Path.Combine(WorkFolder, project);\n            _logger?.WriteLine($\"Project directory: '{project}'\");\n\n            var process = new Process\n            {\n                EnableRaisingEvents = true,\n                StartInfo = new ProcessStartInfo\n                {\n                    FileName = DotNetMuxer.MuxerPathOrDefault(),\n                    Arguments = ArgumentEscaper.EscapeAndConcatenate(arguments),\n                    WorkingDirectory = project,\n                    RedirectStandardOutput = true,\n                    RedirectStandardError = true,\n                    Environment =\n                    {\n                        [\"DOTNET_SKIP_FIRST_TIME_EXPERIENCE\"] = \"true\"\n                    }\n                },\n            };\n\n            void OnData(object sender, DataReceivedEventArgs args)\n              => _logger?.WriteLine(args.Data ?? string.Empty);\n\n            void OnExit(object sender, EventArgs args)\n            {\n                _logger?.WriteLine($\"Process exited {process.Id}\");\n                tcs.TrySetResult(null);\n            }\n\n            process.ErrorDataReceived += OnData;\n            process.OutputDataReceived += OnData;\n            process.Exited += OnExit;\n\n            process.Start();\n\n            process.BeginErrorReadLine();\n            process.BeginOutputReadLine();\n\n            _logger?.WriteLine($\"Started process {process.Id}: {process.StartInfo.FileName} {process.StartInfo.Arguments}\");\n\n            var done = await Task.WhenAny(tcs.Task, Task.Delay(timeout));\n            process.CancelErrorRead();\n            process.CancelOutputRead();\n\n            process.ErrorDataReceived -= OnData;\n            process.OutputDataReceived -= OnData;\n            process.Exited -= OnExit;\n\n            if (!ReferenceEquals(done, tcs.Task))\n            {\n                if (!process.HasExited)\n                {\n                    _logger?.WriteLine($\"Killing process {process.Id}\");\n                    process.KillTree();\n                }\n\n                throw new TimeoutException($\"Process timed out after {timeout.TotalSeconds} seconds\");\n            }\n\n            _logger?.WriteLine($\"Process exited {process.Id} with code {process.ExitCode}\");\n            if (process.ExitCode != 0)\n            {\n\n                throw new InvalidOperationException($\"Exit code {process.ExitCode}\");\n            }\n        }\n\n        private void CreateTestDirectory()\n        {\n            Directory.CreateDirectory(WorkFolder);\n\n            File.WriteAllText(Path.Combine(WorkFolder, \"Directory.Build.props\"), \"<Project />\");\n\n            var restoreSources = GetMetadata(\"TestSettings:RestoreSources\");\n            var frameworkVersion = GetMetadata(\"TestSettings:RuntimeFrameworkVersion\");\n\n            var dbTargets = new XDocument(\n                new XElement(\"Project\",\n                    new XElement(\"PropertyGroup\",\n                        new XElement(\"RuntimeFrameworkVersion\", frameworkVersion),\n                        new XElement(\"RestoreSources\", restoreSources))));\n            dbTargets.Save(Path.Combine(WorkFolder, \"Directory.Build.targets\"));\n        }\n\n        private string GetMetadata(string key)\n        {\n            return typeof(ProjectToolScenario)\n                .Assembly\n                .GetCustomAttributes<AssemblyMetadataAttribute>()\n                .First(a => string.Equals(a.Key, key, StringComparison.Ordinal))\n                .Value;\n        }\n\n        public void Dispose()\n        {\n            try\n            {\n                Directory.Delete(WorkFolder, recursive: true);\n            }\n            catch\n            {\n                Console.WriteLine($\"Failed to delete {WorkFolder}. Retrying...\");\n                Thread.Sleep(TimeSpan.FromSeconds(5));\n                Directory.Delete(WorkFolder, recursive: true);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Threading.Tasks;\nusing Microsoft.Extensions.CommandLineUtils;\nusing Xunit.Abstractions;\n\nnamespace Microsoft.DotNet.Watcher.Tools.FunctionalTests\n{\n    public class WatchableApp : IDisposable\n    {\n        private static readonly TimeSpan DefaultMessageTimeOut = TimeSpan.FromSeconds(30);\n\n        private const string StartedMessage = \"Started\";\n        private const string ExitingMessage = \"Exiting\";\n        private const string WatchExitedMessage = \"watch : Exited\";\n        private const string WaitingForFileChangeMessage = \"watch : Waiting for a file to change\";\n\n        private readonly ITestOutputHelper _logger;\n        private string _appName;\n        private bool _prepared;\n\n\n        public WatchableApp(string appName, ITestOutputHelper logger)\n        {\n            _logger = logger;\n            _appName = appName;\n            Scenario = new ProjectToolScenario(logger);\n            Scenario.AddTestProjectFolder(appName);\n            SourceDirectory = Path.Combine(Scenario.WorkFolder, appName);\n        }\n\n        public ProjectToolScenario Scenario { get; }\n\n        public AwaitableProcess Process { get; protected set; }\n\n        public string SourceDirectory { get; }\n\n        public Task HasRestarted()\n            => Process.GetOutputLineAsync(StartedMessage, DefaultMessageTimeOut);\n\n        public async Task HasExited()\n        {\n            await Process.GetOutputLineAsync(ExitingMessage, DefaultMessageTimeOut);\n            await Process.GetOutputLineStartsWithAsync(WatchExitedMessage, DefaultMessageTimeOut);\n        }\n\n        public async Task IsWaitingForFileChange()\n        {\n            await Process.GetOutputLineStartsWithAsync(WaitingForFileChangeMessage, DefaultMessageTimeOut);\n        }\n\n        public bool UsePollingWatcher { get; set; }\n\n        public async Task<string> GetProcessIdentifier()\n        {\n            // Process ID is insufficient because PID's may be reused. Process identifier also includes other info to distinguish\n            // between different process instances.\n            var line = await Process.GetOutputLineStartsWithAsync(\"Process identifier =\", DefaultMessageTimeOut);\n            return line.Split('=').Last();\n        }\n\n        public async Task PrepareAsync()\n        {\n            await Scenario.RestoreAsync(_appName);\n            await Scenario.BuildAsync(_appName);\n            _prepared = true;\n        }\n\n        public void Start(IEnumerable<string> arguments, [CallerMemberName] string name = null)\n        {\n            if (!_prepared)\n            {\n                throw new InvalidOperationException($\"Call {nameof(PrepareAsync)} first\");\n            }\n\n            var args = new List<string>\n            {\n                Scenario.DotNetWatchPath,\n            };\n            args.AddRange(arguments);\n\n            var spec = new ProcessSpec\n            {\n                Executable = DotNetMuxer.MuxerPathOrDefault(),\n                Arguments = args,\n                WorkingDirectory = SourceDirectory,\n                EnvironmentVariables =\n                {\n                    [\"DOTNET_CLI_CONTEXT_VERBOSE\"] = bool.TrueString,\n                    [\"DOTNET_USE_POLLING_FILE_WATCHER\"] = UsePollingWatcher.ToString(),\n                },\n            };\n\n            Process = new AwaitableProcess(spec, _logger);\n            Process.Start();\n        }\n\n        public Task StartWatcherAsync([CallerMemberName] string name = null)\n            => StartWatcherAsync(Array.Empty<string>(), name);\n\n        public async Task StartWatcherAsync(string[] arguments, [CallerMemberName] string name = null)\n        {\n            if (!_prepared)\n            {\n                await PrepareAsync();\n            }\n\n            var args = new[] { \"run\", \"--\" }.Concat(arguments);\n            Start(args, name);\n\n            // Make this timeout long because it depends much on the MSBuild compilation speed.\n            // Slow machines may take a bit to compile and boot test apps\n            await Process.GetOutputLineAsync(StartedMessage, TimeSpan.FromMinutes(2));\n        }\n\n        public virtual void Dispose()\n        {\n            _logger?.WriteLine(\"Disposing WatchableApp\");\n            Process?.Dispose();\n            Scenario?.Dispose();\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n    <OutputType>exe</OutputType>\n    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>\n\n    <!-- aspnet/BuildTools#662 Don't police what version of NetCoreApp we use -->\n    <NETCoreAppMaximumVersion>99.9</NETCoreAppMaximumVersion>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\Dependency\\Dependency.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/Program.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Diagnostics;\nusing System.Threading;\n\nnamespace ConsoleApplication\n{\n    public class Program\n    {\n        private static readonly int processId = Process.GetCurrentProcess().Id;\n\n        public static void Main(string[] args)\n        {\n            Console.WriteLine(\"Started\");\n            // Process ID is insufficient because PID's may be reused.\n            Console.WriteLine($\"Process identifier = {Process.GetCurrentProcess().Id}, {Process.GetCurrentProcess().StartTime:hh:mm:ss.FF}\");\n            Thread.Sleep(Timeout.Infinite);\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/TestProjects/Dependency/Dependency.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>\n  </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/TestProjects/Dependency/Foo.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Dependency\n{\n    public class Foo\n    {\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n    <OutputType>exe</OutputType>\n    <EnableDefaultCompileItems>false</EnableDefaultCompileItems>\n    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>\n\n    <!-- aspnet/BuildTools#662 Don't police what version of NetCoreApp we use -->\n    <NETCoreAppMaximumVersion>99.9</NETCoreAppMaximumVersion>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Compile Include=\"Program.cs;include\\*.cs\" Exclude=\"exclude\\*\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/Program.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Diagnostics;\nusing System.Linq;\nusing System.Reflection;\nusing System.Threading;\n\nnamespace ConsoleApplication\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            Console.WriteLine(\"Started\");\n            // Process ID is insufficient because PID's may be reused.\n            Console.WriteLine($\"Process identifier = {Process.GetCurrentProcess().Id}, {Process.GetCurrentProcess().StartTime:hh:mm:ss.FF}\");\n            Console.WriteLine(\"Defined types = \" + typeof(Program).GetTypeInfo().Assembly.DefinedTypes.Count());\n            Thread.Sleep(Timeout.Infinite);\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/exclude/Baz.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace GlobbingApp.exclude\n{\n    public class Baz\n    {\n        \"THIS FILE SHOULD NOT BE INCLUDED IN COMPILATION\"\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/include/Foo.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace GlobbingApp.include\n{\n    public class Foo\n    {\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj",
    "content": "<Project>\n\n  <PropertyGroup>\n    <BaseIntermediateOutputPath>.net/obj</BaseIntermediateOutputPath>\n    <BaseOutputPath>.net/bin</BaseOutputPath>\n  </PropertyGroup>\n\n  <Import Project=\"Sdk.props\" Sdk=\"Microsoft.NET.Sdk\" />\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>\n\n    <!-- aspnet/BuildTools#662 Don't police what version of NetCoreApp we use -->\n    <NETCoreAppMaximumVersion>99.9</NETCoreAppMaximumVersion>\n  </PropertyGroup>\n\n  <Import Project=\"Sdk.targets\" Sdk=\"Microsoft.NET.Sdk\" />\n\n</Project>\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/Program.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Diagnostics;\n\nnamespace KitchenSink\n{\n    class Program\n    {\n        static void Main(string[] args)\n        {\n            Console.WriteLine(\"Started\");\n            // Process ID is insufficient because PID's may be reused.\n            Console.WriteLine($\"Process identifier = {Process.GetCurrentProcess().Id}, {Process.GetCurrentProcess().StartTime:hh:mm:ss.FF}\");\n            Console.WriteLine(\"DOTNET_WATCH = \" + Environment.GetEnvironmentVariable(\"DOTNET_WATCH\"));\n            Console.WriteLine(\"DOTNET_WATCH_ITERATION = \" + Environment.GetEnvironmentVariable(\"DOTNET_WATCH_ITERATION\"));\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n    <OutputType>exe</OutputType>\n    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>\n\n    <!-- aspnet/BuildTools#662 Don't police what version of NetCoreApp we use -->\n    <NETCoreAppMaximumVersion>99.9</NETCoreAppMaximumVersion>\n  </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/Program.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Diagnostics;\nusing System.Threading;\n\nnamespace ConsoleApplication\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            Console.WriteLine(\"Started\");\n            // Process ID is insufficient because PID's may be reused.\n            Console.WriteLine($\"Process identifier = {Process.GetCurrentProcess().Id}, {Process.GetCurrentProcess().StartTime:hh:mm:ss.FF}\");\n            if (args.Length > 0 && args[0] == \"--no-exit\")\n            {\n                Thread.Sleep(Timeout.Infinite);\n            }\n            Console.WriteLine(\"Exiting\");\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n    <DefaultItemExcludes>$(DefaultItemExcludes);TestProjects\\**\\*</DefaultItemExcludes>\n    <AssemblyName>Microsoft.DotNet.Watcher.Tools.FunctionalTests</AssemblyName>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Compile Include=\"..\\Shared\\**\\*.cs\" />\n    <Content Include=\"TestProjects\\**\\*\" CopyToOutputDirectory=\"PreserveNewest\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\dotnet-watch\\dotnet-watch.csproj\" />\n    <ProjectReference Include=\"..\\dotnet-watch.Tests\\dotnet-watch.Tests.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.Extensions.Process.Sources\" PrivateAssets=\"All\" Version=\"$(MicrosoftExtensionsProcessSourcesPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.CommandLineUtils.Sources\" PrivateAssets=\"All\" Version=\"$(MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion)\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <AssemblyAttribute Include=\"System.Reflection.AssemblyMetadataAttribute\">\n      <_Parameter1>TestSettings:RestoreSources</_Parameter1>\n      <_Parameter2>$(RestoreSources)</_Parameter2>\n    </AssemblyAttribute>\n     <AssemblyAttribute Include=\"System.Reflection.AssemblyMetadataAttribute\">\n      <_Parameter1>TestSettings:RuntimeFrameworkVersion</_Parameter1>\n      <_Parameter2>$(RuntimeFrameworkVersion)</_Parameter2>\n    </AssemblyAttribute>\n  </ItemGroup>\n\n  <Target Name=\"CleanTestProjects\" BeforeTargets=\"CoreCompile\">\n    <RemoveDir Directories=\"$(TargetDir)TestProjects\" Condition=\"Exists('$(TargetDir)TestProjects')\" />\n  </Target>\n\n  <Target Name=\"PublishDotNetWatch\" BeforeTargets=\"Build\">\n    <MSBuild Projects=\"..\\..\\src\\dotnet-watch\\dotnet-watch.csproj\"\n      Targets=\"Publish\"\n      Properties=\"PublishDir=$(OutputPath)\\tool\\;Configuration=$(Configuration)\" />\n  </Target>\n\n</Project>\n"
  },
  {
    "path": "test/dotnet-watch.Tests/AssertEx.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing Xunit;\nusing Xunit.Sdk;\n\nnamespace Microsoft.DotNet.Watcher.Tools.Tests\n{\n    public static class AssertEx\n    {\n        public static void EqualFileList(string root, IEnumerable<string> expectedFiles, IEnumerable<string> actualFiles)\n        {\n            var expected = expectedFiles.Select(p => Path.Combine(root, p));\n            EqualFileList(expected, actualFiles);\n        }\n\n        public static void EqualFileList(IEnumerable<string> expectedFiles, IEnumerable<string> actualFiles)\n        {\n            string normalize(string p) => p.Replace('\\\\', '/');\n            var expected = new HashSet<string>(expectedFiles.Select(normalize));\n            var actual = new HashSet<string>(actualFiles.Where(p => !string.IsNullOrEmpty(p)).Select(normalize));\n            if (!expected.SetEquals(actual))\n            {\n                throw new AssertActualExpectedException(\n                    expected: \"\\n\" + string.Join(\"\\n\", expected),\n                    actual:  \"\\n\" + string.Join(\"\\n\", actual),\n                    userMessage: \"File sets should be equal\");\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.Tests/CommandLineOptionsTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing Microsoft.Extensions.CommandLineUtils;\nusing Microsoft.Extensions.Tools.Internal;\nusing Xunit;\nusing Xunit.Abstractions;\n\nnamespace Microsoft.DotNet.Watcher.Tools.Tests\n{\n    public class CommandLineOptionsTests\n    {\n        private readonly IConsole _console;\n        private readonly StringBuilder _stdout = new StringBuilder();\n\n        public CommandLineOptionsTests(ITestOutputHelper output)\n        {\n            _console = new TestConsole(output)\n            {\n                Out = new StringWriter(_stdout),\n            };\n        }\n\n        [Theory]\n        [InlineData(new object[] { new[] { \"-h\" } })]\n        [InlineData(new object[] { new[] { \"-?\" } })]\n        [InlineData(new object[] { new[] { \"--help\" } })]\n        [InlineData(new object[] { new[] { \"--help\", \"--bogus\" } })]\n        [InlineData(new object[] { new[] { \"--\" } })]\n        [InlineData(new object[] { new string[0] })]\n        public void HelpArgs(string[] args)\n        {\n            var options = CommandLineOptions.Parse(args, _console);\n\n            Assert.True(options.IsHelp);\n            Assert.Contains(\"Usage: dotnet watch \", _stdout.ToString());\n        }\n\n        [Theory]\n        [InlineData(new[] { \"run\" }, new[] { \"run\" })]\n        [InlineData(new[] { \"run\", \"--\", \"subarg\" }, new[] { \"run\", \"--\", \"subarg\" })]\n        [InlineData(new[] { \"--\", \"run\", \"--\", \"subarg\" }, new[] { \"run\", \"--\", \"subarg\" })]\n        [InlineData(new[] { \"--unrecognized-arg\" }, new[] { \"--unrecognized-arg\" })]\n        public void ParsesRemainingArgs(string[] args, string[] expected)\n        {\n            var options = CommandLineOptions.Parse(args, _console);\n\n            Assert.Equal(expected, options.RemainingArguments.ToArray());\n            Assert.False(options.IsHelp);\n            Assert.Empty(_stdout.ToString());\n        }\n\n        [Fact]\n        public void CannotHaveQuietAndVerbose()\n        {\n            var ex = Assert.Throws<CommandParsingException>(() => CommandLineOptions.Parse(new[] { \"--quiet\", \"--verbose\" }, _console));\n            Assert.Equal(Resources.Error_QuietAndVerboseSpecified, ex.Message);\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.Tests/ConsoleReporterTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Text;\nusing Microsoft.Extensions.Tools.Internal;\nusing Xunit;\n\nnamespace Microsoft.Extensions.Tools.Tests\n{\n    public class ReporterTests\n    {\n        private static readonly string EOL = Environment.NewLine;\n\n        [Fact]\n        public void WritesToStandardStreams()\n        {\n            var testConsole = new TestConsole();\n            var reporter = new ConsoleReporter(testConsole, verbose: true, quiet: false);\n\n            // stdout\n            reporter.Verbose(\"verbose\");\n            Assert.Equal(\"verbose\" + EOL, testConsole.GetOutput());\n            testConsole.Clear();\n\n            reporter.Output(\"out\");\n            Assert.Equal(\"out\" + EOL, testConsole.GetOutput());\n            testConsole.Clear();\n\n            reporter.Warn(\"warn\");\n            Assert.Equal(\"warn\" + EOL, testConsole.GetOutput());\n            testConsole.Clear();\n\n            // stderr\n            reporter.Error(\"error\");\n            Assert.Equal(\"error\" + EOL, testConsole.GetError());\n            testConsole.Clear();\n        }\n\n        private class TestConsole : IConsole\n        {\n            private readonly StringBuilder _out;\n            private readonly StringBuilder _error;\n\n            public TestConsole()\n            {\n                _out = new StringBuilder();\n                _error = new StringBuilder();\n                Out = new StringWriter(_out);\n                Error = new StringWriter(_error);\n            }\n\n            event ConsoleCancelEventHandler IConsole.CancelKeyPress\n            {\n                add { }\n                remove { }\n            }\n\n            public string GetOutput() => _out.ToString();\n            public string GetError() => _error.ToString();\n\n            public void Clear()\n            {\n                _out.Clear();\n                _error.Clear();\n            }\n\n            public void ResetColor()\n            {\n                ForegroundColor = default(ConsoleColor);\n            }\n\n            public TextWriter Out { get; }\n            public TextWriter Error { get; }\n            public TextReader In { get; }\n            public bool IsInputRedirected { get; }\n            public bool IsOutputRedirected { get; }\n            public bool IsErrorRedirected { get; }\n            public ConsoleColor ForegroundColor { get; set; }\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Linq;\nusing System.Text.RegularExpressions;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Testing;\nusing Microsoft.DotNet.Watcher.Internal;\nusing Microsoft.Extensions.Tools.Internal;\nusing Xunit;\nusing Xunit.Abstractions;\n\nnamespace Microsoft.DotNet.Watcher.Tools.Tests\n{\n    using ItemSpec = TemporaryCSharpProject.ItemSpec;\n\n    public class MsBuildFileSetFactoryTest : IDisposable\n    {\n        private readonly IReporter _reporter;\n        private readonly TemporaryDirectory _tempDir;\n        public MsBuildFileSetFactoryTest(ITestOutputHelper output)\n        {\n            _reporter = new TestReporter(output);\n            _tempDir = new TemporaryDirectory();\n        }\n\n        [Fact]\n        public async Task FindsCustomWatchItems()\n        {\n            _tempDir\n                .WithCSharpProject(\"Project1\", out var target)\n                    .WithTargetFrameworks(\"netcoreapp1.0\")\n                    .WithItem(new ItemSpec { Name = \"Watch\", Include = \"*.js\", Exclude = \"gulpfile.js\" })\n                    .Dir()\n                    .WithFile(\"Program.cs\")\n                    .WithFile(\"app.js\")\n                    .WithFile(\"gulpfile.js\");\n\n            var fileset = await GetFileSet(target);\n\n            AssertEx.EqualFileList(\n                _tempDir.Root,\n                new[]\n                {\n                    \"Project1.csproj\",\n                    \"Program.cs\",\n                    \"app.js\"\n                },\n                fileset\n            );\n        }\n\n        [Fact]\n        public async Task ExcludesDefaultItemsWithWatchFalseMetadata()\n        {\n            _tempDir\n                .WithCSharpProject(\"Project1\", out var target)\n                    .WithTargetFrameworks(\"net40\")\n                    .WithItem(new ItemSpec { Name = \"EmbeddedResource\", Update = \"*.resx\", Watch = false })\n                    .Dir()\n                    .WithFile(\"Program.cs\")\n                    .WithFile(\"Strings.resx\");\n\n            var fileset = await GetFileSet(target);\n\n            AssertEx.EqualFileList(\n                _tempDir.Root,\n                new[]\n                {\n                    \"Project1.csproj\",\n                    \"Program.cs\",\n                },\n                fileset\n            );\n        }\n\n        [Fact]\n        public async Task SingleTfm()\n        {\n            _tempDir\n                .SubDir(\"src\")\n                    .SubDir(\"Project1\")\n                        .WithCSharpProject(\"Project1\", out var target)\n                        .WithProperty(\"BaseIntermediateOutputPath\", \"obj\")\n                        .WithTargetFrameworks(\"netcoreapp1.0\")\n                        .Dir()\n                        .WithFile(\"Program.cs\")\n                        .WithFile(\"Class1.cs\")\n                        .SubDir(\"obj\").WithFile(\"ignored.cs\").Up()\n                        .SubDir(\"Properties\").WithFile(\"Strings.resx\").Up()\n                    .Up()\n                .Up()\n                .Create();\n\n            var fileset = await GetFileSet(target);\n\n            AssertEx.EqualFileList(\n                _tempDir.Root,\n                new[]\n                {\n                    \"src/Project1/Project1.csproj\",\n                    \"src/Project1/Program.cs\",\n                    \"src/Project1/Class1.cs\",\n                    \"src/Project1/Properties/Strings.resx\",\n                },\n                fileset\n            );\n        }\n\n        [Fact]\n        public async Task MultiTfm()\n        {\n            _tempDir\n               .SubDir(\"src\")\n                   .SubDir(\"Project1\")\n                       .WithCSharpProject(\"Project1\", out var target)\n                       .WithTargetFrameworks(\"netcoreapp1.0\", \"net451\")\n                       .WithProperty(\"EnableDefaultCompileItems\", \"false\")\n                       .WithItem(\"Compile\", \"Class1.netcore.cs\", \"'$(TargetFramework)'=='netcoreapp1.0'\")\n                       .WithItem(\"Compile\", \"Class1.desktop.cs\", \"'$(TargetFramework)'=='net451'\")\n                       .Dir()\n                       .WithFile(\"Class1.netcore.cs\")\n                       .WithFile(\"Class1.desktop.cs\")\n                       .WithFile(\"Class1.notincluded.cs\");\n\n            var fileset = await GetFileSet(target);\n\n            AssertEx.EqualFileList(\n                _tempDir.Root,\n                new[]\n                {\n                    \"src/Project1/Project1.csproj\",\n                    \"src/Project1/Class1.netcore.cs\",\n                    \"src/Project1/Class1.desktop.cs\",\n                },\n                fileset\n            );\n        }\n\n        [Fact]\n        public async Task ProjectReferences_OneLevel()\n        {\n            _tempDir\n                .SubDir(\"src\")\n                    .SubDir(\"Project2\")\n                        .WithCSharpProject(\"Project2\", out var proj2)\n                        .WithTargetFrameworks(\"netstandard1.1\")\n                        .Dir()\n                        .WithFile(\"Class2.cs\")\n                    .Up()\n                    .SubDir(\"Project1\")\n                        .WithCSharpProject(\"Project1\", out var target)\n                        .WithTargetFrameworks(\"netcoreapp1.0\", \"net451\")\n                        .WithProjectReference(proj2)\n                        .Dir()\n                        .WithFile(\"Class1.cs\");\n\n            var fileset = await GetFileSet(target);\n\n            AssertEx.EqualFileList(\n                _tempDir.Root,\n                new[]\n                {\n                    \"src/Project2/Project2.csproj\",\n                    \"src/Project2/Class2.cs\",\n                    \"src/Project1/Project1.csproj\",\n                    \"src/Project1/Class1.cs\",\n                },\n                fileset\n            );\n        }\n\n        [Fact]\n        public async Task TransitiveProjectReferences_TwoLevels()\n        {\n            _tempDir\n                .SubDir(\"src\")\n                    .SubDir(\"Project3\")\n                        .WithCSharpProject(\"Project3\", out var proj3)\n                        .WithTargetFrameworks(\"netstandard1.0\")\n                        .Dir()\n                        .WithFile(\"Class3.cs\")\n                    .Up()\n                    .SubDir(\"Project2\")\n                        .WithCSharpProject(\"Project2\", out TemporaryCSharpProject proj2)\n                        .WithTargetFrameworks(\"netstandard1.1\")\n                        .WithProjectReference(proj3)\n                        .Dir()\n                        .WithFile(\"Class2.cs\")\n                    .Up()\n                    .SubDir(\"Project1\")\n                        .WithCSharpProject(\"Project1\", out TemporaryCSharpProject target)\n                        .WithTargetFrameworks(\"netcoreapp1.0\", \"net451\")\n                        .WithProjectReference(proj2)\n                        .Dir()\n                        .WithFile(\"Class1.cs\");\n\n            var fileset = await GetFileSet(target);\n\n            AssertEx.EqualFileList(\n                _tempDir.Root,\n                new[]\n                {\n                    \"src/Project3/Project3.csproj\",\n                    \"src/Project3/Class3.cs\",\n                    \"src/Project2/Project2.csproj\",\n                    \"src/Project2/Class2.cs\",\n                    \"src/Project1/Project1.csproj\",\n                    \"src/Project1/Class1.cs\",\n                },\n                fileset\n            );\n        }\n\n        [Fact]\n        public async Task ProjectReferences_Graph()\n        {\n            var graph = new TestProjectGraph(_tempDir);\n            graph.OnCreate(p => p.WithTargetFrameworks(\"net45\"));\n            var matches = Regex.Matches(@\"\n            A->B B->C C->D D->E\n                 B->E\n            A->F F->G G->E\n                 F->E\n            W->U\n            Y->Z\n            Y->B\n            Y->F\",\n            @\"(\\w)->(\\w)\");\n\n            Assert.Equal(13, matches.Count);\n            foreach (Match m in matches)\n            {\n                var target = graph.GetOrCreate(m.Groups[2].Value);\n                graph.GetOrCreate(m.Groups[1].Value).WithProjectReference(target);\n            }\n\n            graph.Find(\"A\").WithProjectReference(graph.Find(\"W\"), watch: false);\n\n            var output = new OutputSink();\n            var filesetFactory = new MsBuildFileSetFactory(_reporter, graph.GetOrCreate(\"A\").Path, output, trace: true);\n\n            var fileset = await GetFileSet(filesetFactory);\n\n            _reporter.Output(string.Join(\n                Environment.NewLine,\n                output.Current.Lines.Select(l => \"Sink output: \" + l)));\n\n            var includedProjects = new[] { \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\" };\n            AssertEx.EqualFileList(\n                _tempDir.Root,\n                includedProjects\n                    .Select(p => $\"{p}/{p}.csproj\"),\n                fileset\n            );\n\n            // ensure unreachable projects exist but where not included\n            Assert.NotNull(graph.Find(\"W\"));\n            Assert.NotNull(graph.Find(\"U\"));\n            Assert.NotNull(graph.Find(\"Y\"));\n            Assert.NotNull(graph.Find(\"Z\"));\n\n            // ensure each project is only visited once for collecting watch items\n            Assert.All(includedProjects,\n                projectName =>\n                    Assert.Single(output.Current.Lines,\n                        line => line.Contains($\"Collecting watch items from '{projectName}'\"))\n            );\n        }\n\n        private Task<IFileSet> GetFileSet(TemporaryCSharpProject target)\n            => GetFileSet(new MsBuildFileSetFactory(_reporter, target.Path, waitOnError: false, trace: false));\n\n        private async Task<IFileSet> GetFileSet(MsBuildFileSetFactory filesetFactory)\n        {\n            _tempDir.Create();\n            return await filesetFactory\n                .CreateAsync(CancellationToken.None)\n                .TimeoutAfter(TimeSpan.FromSeconds(30));\n        }\n\n        public void Dispose()\n        {\n            _tempDir.Dispose();\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.Tests/ProgramTests.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Testing;\nusing Microsoft.Extensions.Tools.Internal;\nusing Xunit;\nusing Xunit.Abstractions;\n\nnamespace Microsoft.DotNet.Watcher.Tools.Tests\n{\n    public class ProgramTests : IDisposable\n    {\n        private readonly TemporaryDirectory _tempDir;\n        private readonly TestConsole _console;\n\n        public ProgramTests(ITestOutputHelper output)\n        {\n            _tempDir = new TemporaryDirectory();\n            _console = new TestConsole(output);\n        }\n\n        [Fact]\n        public async Task ConsoleCancelKey()\n        {\n            _tempDir\n                .WithCSharpProject(\"testproj\")\n                .WithTargetFrameworks(\"netcoreapp3.0\")\n                .Dir()\n                .WithFile(\"Program.cs\")\n                .Create();\n\n            var output = new StringBuilder();\n            _console.Error = _console.Out = new StringWriter(output);\n            using (var app = new Program(_console, _tempDir.Root))\n            {\n                var run = app.RunAsync(new[] { \"run\" });\n\n                await _console.CancelKeyPressSubscribed.TimeoutAfter(TimeSpan.FromSeconds(30));\n                _console.ConsoleCancelKey();\n\n                var exitCode = await run.TimeoutAfter(TimeSpan.FromSeconds(30));\n\n                Assert.Contains(\"Shutdown requested. Press Ctrl+C again to force exit.\", output.ToString());\n                Assert.Equal(0, exitCode);\n            }\n        }\n\n        public void Dispose()\n        {\n            _tempDir.Dispose();\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.Tests/Utilities/TemporaryCSharpProject.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Text;\n\nnamespace Microsoft.DotNet.Watcher.Tools.Tests\n{\n    public class TemporaryCSharpProject\n    {\n        private const string Template =\n @\"<Project Sdk=\"\"Microsoft.NET.Sdk\"\">\n  <PropertyGroup>\n    {0}\n    <OutputType>Exe</OutputType>\n  </PropertyGroup>\n  <ItemGroup>\n    {1}\n  </ItemGroup>\n</Project>\";\n\n        private readonly string _filename;\n        private readonly TemporaryDirectory _directory;\n        private List<string> _items = new List<string>();\n        private List<string> _properties = new List<string>();\n\n        public TemporaryCSharpProject(string name, TemporaryDirectory directory)\n        {\n            Name = name;\n            _filename = name + \".csproj\";\n            _directory = directory;\n        }\n\n        public string Name { get; }\n        public string Path => System.IO.Path.Combine(_directory.Root, _filename);\n\n        public TemporaryCSharpProject WithTargetFrameworks(params string[] tfms)\n        {\n            Debug.Assert(tfms.Length > 0);\n            var propertySpec = new PropertySpec\n            {\n                Value = string.Join(\";\", tfms)\n            };\n            propertySpec.Name = tfms.Length == 1\n                ? \"TargetFramework\"\n                : \"TargetFrameworks\";\n\n            return WithProperty(propertySpec);\n        }\n\n        public TemporaryCSharpProject WithProperty(string name, string value)\n            => WithProperty(new PropertySpec { Name = name, Value = value });\n\n        public TemporaryCSharpProject WithProperty(PropertySpec property)\n        {\n            var sb = new StringBuilder();\n            sb.Append('<').Append(property.Name).Append('>')\n                .Append(property.Value)\n                .Append(\"</\").Append(property.Name).Append('>');\n            _properties.Add(sb.ToString());\n            return this;\n        }\n\n        public TemporaryCSharpProject WithItem(string itemName, string include, string condition = null)\n            => WithItem(new ItemSpec { Name = itemName, Include = include, Condition = condition });\n\n        public TemporaryCSharpProject WithItem(ItemSpec item)\n        {\n            var sb = new StringBuilder(\"<\");\n            sb.Append(item.Name).Append(\" \");\n            if (item.Include != null) sb.Append(\" Include=\\\"\").Append(item.Include).Append('\"');\n            if (item.Remove != null) sb.Append(\" Remove=\\\"\").Append(item.Remove).Append('\"');\n            if (item.Update != null) sb.Append(\" Update=\\\"\").Append(item.Update).Append('\"');\n            if (item.Exclude != null) sb.Append(\" Exclude=\\\"\").Append(item.Exclude).Append('\"');\n            if (item.Condition != null) sb.Append(\" Exclude=\\\"\").Append(item.Condition).Append('\"');\n            if (!item.Watch) sb.Append(\" Watch=\\\"false\\\" \");\n            sb.Append(\" />\");\n            _items.Add(sb.ToString());\n            return this;\n        }\n\n        public TemporaryCSharpProject WithProjectReference(TemporaryCSharpProject reference, bool watch = true)\n        {\n            if (ReferenceEquals(this, reference))\n            {\n                throw new InvalidOperationException(\"Can add project reference to self\");\n            }\n\n            return WithItem(new ItemSpec { Name = \"ProjectReference\", Include = reference.Path, Watch = watch });\n        }\n\n        public TemporaryDirectory Dir() => _directory;\n\n        public void Create()\n        {\n            _directory.CreateFile(_filename, string.Format(Template, string.Join(\"\\r\\n\", _properties), string.Join(\"\\r\\n\", _items)));\n        }\n\n        public class ItemSpec\n        {\n            public string Name { get; set; }\n            public string Include { get; set; }\n            public string Exclude { get; set; }\n            public string Update { get; set; }\n            public string Remove { get; set; }\n            public bool Watch { get; set; } = true;\n            public string Condition { get; set; }\n        }\n\n        public class PropertySpec\n        {\n            public string Name { get; set; }\n            public string Value { get; set; }\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.Tests/Utilities/TemporaryDirectory.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\n\nnamespace Microsoft.DotNet.Watcher.Tools.Tests\n{\n    public class TemporaryDirectory : IDisposable\n    {\n        private List<TemporaryCSharpProject> _projects = new List<TemporaryCSharpProject>();\n        private List<TemporaryDirectory> _subdirs = new List<TemporaryDirectory>();\n        private Dictionary<string, string> _files = new Dictionary<string, string>();\n        private TemporaryDirectory _parent;\n\n        public TemporaryDirectory()\n        {\n            Root = Path.Combine(Path.GetTempPath(), \"dotnet-watch-tests\", Guid.NewGuid().ToString(\"N\"));\n        }\n\n        private TemporaryDirectory(string path, TemporaryDirectory parent)\n        {\n            _parent = parent;\n            Root = path;\n        }\n\n        public TemporaryDirectory SubDir(string name)\n        {\n            var subdir = new TemporaryDirectory(Path.Combine(Root, name), this);\n            _subdirs.Add(subdir);\n            return subdir;\n        }\n\n        public string Root { get; }\n\n        public TemporaryCSharpProject WithCSharpProject(string name)\n        {\n            var project = new TemporaryCSharpProject(name, this);\n            _projects.Add(project);\n            return project;\n        }\n\n        public TemporaryCSharpProject WithCSharpProject(string name, out TemporaryCSharpProject project)\n        {\n            project = WithCSharpProject(name);\n            return project;\n        }\n\n        public TemporaryDirectory WithFile(string name, string contents = \"\")\n        {\n            _files[name] = contents;\n            return this;\n        }\n\n        public TemporaryDirectory Up()\n        {\n            if (_parent == null)\n            {\n                throw new InvalidOperationException(\"This is the root directory\");\n            }\n            return _parent;\n        }\n\n        public void Create()\n        {\n            Directory.CreateDirectory(Root);\n\n            foreach (var dir in _subdirs)\n            {\n                dir.Create();\n            }\n\n            foreach (var project in _projects)\n            {\n                project.Create();\n            }\n\n            foreach (var file in _files)\n            {\n                CreateFile(file.Key, file.Value);\n            }\n        }\n\n        public void CreateFile(string filename, string contents)\n        {\n            File.WriteAllText(Path.Combine(Root, filename), contents);\n        }\n\n        public void Dispose()\n        {\n            if (Root == null || !Directory.Exists(Root) || _parent != null)\n            {\n                return;\n            }\n\n            try\n            {\n                Directory.Delete(Root, recursive: true);\n            }\n            catch\n            {\n                Console.Error.WriteLine($\"Test cleanup failed to delete '{Root}'\");\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/dotnet-watch.Tests/Utilities/TestProjectGraph.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace Microsoft.DotNet.Watcher.Tools.Tests\n{\n    public class TestProjectGraph\n    {\n        private readonly TemporaryDirectory _directory;\n        private Action<TemporaryCSharpProject> _onCreate;\n        private Dictionary<string, TemporaryCSharpProject> _projects = new Dictionary<string, TemporaryCSharpProject>();\n        public TestProjectGraph(TemporaryDirectory directory)\n        {\n            _directory = directory;\n        }\n\n        public void OnCreate(Action<TemporaryCSharpProject> onCreate)\n        {\n            _onCreate = onCreate;\n        }\n\n        public TemporaryCSharpProject Find(string projectName)\n            => _projects.ContainsKey(projectName)\n                ? _projects[projectName]\n                : null;\n\n        public TemporaryCSharpProject GetOrCreate(string projectName)\n        {\n            TemporaryCSharpProject sourceProj;\n            if (!_projects.TryGetValue(projectName, out sourceProj))\n            {\n                sourceProj = _directory.SubDir(projectName).WithCSharpProject(projectName);\n                _onCreate?.Invoke(sourceProj);\n                _projects.Add(projectName, sourceProj);\n            }\n            return sourceProj;\n        }\n    }\n}"
  },
  {
    "path": "test/dotnet-watch.Tests/dotnet-watch.Tests.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n    <AssemblyName>Microsoft.DotNet.Watcher.Tools.Tests</AssemblyName>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Compile Include=\"..\\Shared\\**\\*.cs\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\dotnet-watch\\dotnet-watch.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n\n    <!-- Required to place the vsix in the right location by WTE MSI -->\n    <ExtensionInstallationRoot>CommonExtensions</ExtensionInstallationRoot>\n    <ExtensionInstallationFolder>Microsoft\\ASP.NET Core\\UserSecrets</ExtensionInstallationFolder>\n    <IsProductComponent>true</IsProductComponent>\n\n    <ImportDirectoryBuildProps>False</ImportDirectoryBuildProps>\n    <ImportDirectoryBuildTargets>False</ImportDirectoryBuildTargets>\n    <GenerateUserSecretsAttribute>False</GenerateUserSecretsAttribute>\n    <UseCodebase>True</UseCodebase>\n    <SignAssembly>True</SignAssembly>\n    <AssemblyOriginatorKeyFile>..\\..\\build\\Key.snk</AssemblyOriginatorKeyFile>\n    <TreatWarningsAsErrors>True</TreatWarningsAsErrors>\n  </PropertyGroup>\n  <Import Project=\"..\\..\\version.props\" />\n  <Import Project=\"..\\..\\build\\dependencies.props\" />\n  <Import Project=\"..\\..\\build\\sources.props\" />\n  <Import Project=\"$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props\" Condition=\"Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')\" />\n  <PropertyGroup>\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\n    <Platform Condition=\" '$(Platform)' == '' \">AnyCPU</Platform>\n    <SchemaVersion>2.0</SchemaVersion>\n    <ProjectTypeGuids>{82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>\n    <ProjectGuid>{5E117F2E-7152-447F-BF47-59F759EEF3A7}</ProjectGuid>\n    <OutputType>Library</OutputType>\n    <AppDesignerFolder>Properties</AppDesignerFolder>\n    <RootNamespace>Microsoft.VisualStudio.SecretManager</RootNamespace>\n    <AssemblyName>Microsoft.VisualStudio.SecretManager</AssemblyName>\n    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>\n    <GeneratePkgDefFile>true</GeneratePkgDefFile>\n    <IncludeAssemblyInVSIXContainer>true</IncludeAssemblyInVSIXContainer>\n    <IncludeDebugSymbolsInVSIXContainer>false</IncludeDebugSymbolsInVSIXContainer>\n    <IncludeDebugSymbolsInLocalVSIXDeployment>true</IncludeDebugSymbolsInLocalVSIXDeployment>\n    <CopyBuildOutputToOutputDirectory>true</CopyBuildOutputToOutputDirectory>\n    <CopyOutputSymbolsToOutputDirectory>true</CopyOutputSymbolsToOutputDirectory>\n    <StartAction>Program</StartAction>\n    <StartProgram Condition=\"'$(DevEnvDir)' != ''\">$(DevEnvDir)devenv.exe</StartProgram>\n    <StartArguments>/rootsuffix Exp</StartArguments>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' \">\n    <DebugSymbols>true</DebugSymbols>\n    <DebugType>full</DebugType>\n    <Optimize>false</Optimize>\n    <OutputPath>bin\\Debug\\</OutputPath>\n    <DefineConstants>TRACE;DEBUG;EXTENSION_DEVELOPER_MODE</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n    <LangVersion>latest</LangVersion>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' \">\n    <DebugSymbols>true</DebugSymbols>\n    <DebugType>full</DebugType>\n    <Optimize>true</Optimize>\n    <OutputPath>bin\\Release\\</OutputPath>\n    <DefineConstants>TRACE</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n    <LangVersion>latest</LangVersion>\n  </PropertyGroup>\n  <ItemGroup>\n    <Compile Include=\"ProjectLocalSecretsManager.cs\" />\n    <Compile Include=\"Properties\\AssemblyInfo.cs\" />\n    <Compile Include=\"Resources.Designer.cs\" />\n    <Compile Include=\"SecretManagerFactory.cs\" />\n    <Compile Include=\"SecretStore.cs\" />\n    <Compile Include=\"Sources\\ConfigurationPath.cs\" />\n    <Compile Include=\"Sources\\JsonConfigurationFileParser.cs\" />\n    <Compile Include=\"Sources\\PathHelper.cs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"source.extension.vsixmanifest\">\n      <SubType>Designer</SubType>\n    </None>\n  </ItemGroup>\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.VisualStudio.ComponentModelHost\" Version=\"15.0.26606\" />\n    <PackageReference Include=\"Microsoft.VisualStudio.ProjectSystem.Analyzers\" Version=\"16.0.201-pre-g7d366164d0\" />\n    <PackageReference Include=\"Microsoft.VisualStudio.ProjectSystem.SDK.Tools\" Version=\"16.0.201-pre-g7d366164d0\" />\n    <PackageReference Include=\"Microsoft.VisualStudio.ProjectSystem.SDK\" Version=\"16.0.201-pre-g7d366164d0\" />\n    <PackageReference Include=\"Microsoft.VisualStudio.ProjectSystem\" Version=\"16.0.201-pre-g7d366164d0\" />\n    <PackageReference Include=\"Microsoft.VisualStudio.Shell.15.0\" Version=\"15.0.26606\" />\n    <PackageReference Include=\"Microsoft.VisualStudio.Shell.Embeddable\" Version=\"15.6.27002-vsuvscore\" />\n    <PackageReference Include=\"Microsoft.VisualStudio.Text.Data\" Version=\"15.0.26606\" />\n    <PackageReference Include=\"Microsoft.VSSDK.BuildTools\" Version=\"15.1.192\" />\n  </ItemGroup>\n  <!--\n  Begin workaround for https://github.com/dotnet/project-system/issues/2129\n  VS does not support using MSBuild variables for PackageReference items\n  -->\n  <ItemGroup Condition=\"'$(PackageReferencePropsPath)' == ''\">\n    <PackageReference Include=\"Newtonsoft.Json\" Version=\"9.0.1\" />\n  </ItemGroup>\n  <Import Project=\"$(PackageReferencePropsPath)\" Condition=\"'$(PackageReferencePropsPath)' != ''\" />\n  <!-- End workaround -->\n  <ItemGroup>\n    <Reference Include=\"System\" />\n    <Reference Include=\"System.ComponentModel.Composition\" />\n    <Reference Include=\"Microsoft.CSharp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <EmbeddedResource Include=\"Resources.resx\">\n      <SubType>Designer</SubType>\n    </EmbeddedResource>\n  </ItemGroup>\n  <Target Name=\"GetBuildVersion\" Outputs=\"$(VsixVersion)\" />\n  <Import Project=\"$(MSBuildToolsPath)\\Microsoft.CSharp.targets\" />\n  <Import Project=\"$(VSToolsPath)\\VSSDK\\Microsoft.VsSDK.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n\n  <Target Name=\"CopySymbolsToOutput\" AfterTargets=\"Build\" Condition=\"'$(SymbolsPublishDir)' != ''\">\n    <Copy SourceFiles=\"$(OutDir)$(AssemblyName).pdb\" DestinationFolder=\"$(SymbolsPublishDir)\" />\n  </Target>\n</Project>\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager/ProjectLocalSecretsManager.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.VisualStudio.ProjectSystem.Properties;\nusing Microsoft.VisualStudio.Threading;\nusing Task = System.Threading.Tasks.Task;\n\nnamespace Microsoft.VisualStudio.SecretManager\n{\n    /// <summary>\n    /// Provides an thread-safe access the secrets.json file based on the UserSecretsId property in a configured project.\n    /// </summary>\n    internal class ProjectLocalSecretsManager : Shell.IVsProjectSecrets, Shell.SVsProjectLocalSecrets\n    {\n        private const string UserSecretsPropertyName = \"UserSecretsId\";\n\n        private readonly AsyncSemaphore _semaphore;\n        private readonly IProjectPropertiesProvider _propertiesProvider;\n        private readonly Lazy<IServiceProvider> _services;\n\n        public ProjectLocalSecretsManager(IProjectPropertiesProvider propertiesProvider, Lazy<IServiceProvider> serviceProvider)\n        {\n            _propertiesProvider = propertiesProvider ?? throw new ArgumentNullException(nameof(propertiesProvider));\n            _services = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));\n            _semaphore = new AsyncSemaphore(1);\n        }\n\n        public string SanitizeName(string name) => name;\n\n        public IReadOnlyCollection<char> GetInvalidCharactersFrom(string name) => Array.Empty<char>();\n\n        public async Task AddSecretAsync(string name, string value, CancellationToken cancellationToken = default)\n        {\n            EnsureKeyNameIsValid(name);\n            await TaskScheduler.Default;\n\n            using (await _semaphore.EnterAsync(cancellationToken))\n            using (var store = await GetOrCreateStoreAsync(cancellationToken))\n            {\n                if (store.ContainsKey(name))\n                {\n                    throw new ArgumentException(Resources.Error_SecretAlreadyExists, nameof(name));\n                }\n\n                store.Set(name, value);\n                await store.SaveAsync(cancellationToken);\n            }\n        }\n\n        public async Task SetSecretAsync(string name, string value, CancellationToken cancellationToken = default)\n        {\n            EnsureKeyNameIsValid(name);\n            await TaskScheduler.Default;\n\n            using (await _semaphore.EnterAsync(cancellationToken))\n            using (var store = await GetOrCreateStoreAsync(cancellationToken))\n            {\n                store.Set(name, value);\n                await store.SaveAsync(cancellationToken);\n            }\n        }\n\n        public async Task<string> GetSecretAsync(string name, CancellationToken cancellationToken = default)\n        {\n            EnsureKeyNameIsValid(name);\n            await TaskScheduler.Default;\n\n            using (await _semaphore.EnterAsync(cancellationToken))\n            using (var store = await GetOrCreateStoreAsync(cancellationToken))\n            {\n                return store.Get(name);\n            }\n        }\n\n        public async Task<IReadOnlyCollection<string>> GetSecretNamesAsync(CancellationToken cancellationToken = default)\n        {\n            await TaskScheduler.Default;\n\n            using (await _semaphore.EnterAsync(cancellationToken))\n            using (var store = await GetOrCreateStoreAsync(cancellationToken))\n            {\n                return store.ReadOnlyKeys;\n            }\n        }\n\n\n        public async Task<IReadOnlyDictionary<string, string>> GetSecretsAsync(CancellationToken cancellationToken = default)\n        {\n            await TaskScheduler.Default;\n\n            using (await _semaphore.EnterAsync(cancellationToken))\n            using (var store = await GetOrCreateStoreAsync(cancellationToken))\n            {\n                return store.Values;\n            }\n        }\n\n        public async Task<bool> RemoveSecretAsync(string name, CancellationToken cancellationToken = default)\n        {\n            EnsureKeyNameIsValid(name);\n            await TaskScheduler.Default;\n\n            using (await _semaphore.EnterAsync(cancellationToken))\n            using (var store = await GetOrCreateStoreAsync(cancellationToken))\n            {\n                if (store.Remove(name))\n                {\n                    await store.SaveAsync(cancellationToken);\n                    return true;\n                }\n\n                return false;\n            }\n        }\n\n        private void EnsureKeyNameIsValid(string name)\n        {\n            if (name == null)\n            {\n                throw new ArgumentNullException(nameof(name));\n            }\n\n            if (name.Length == 0)\n            {\n                throw new ArgumentException(nameof(name));\n            }\n        }\n\n        private async Task<SecretStore> GetOrCreateStoreAsync(CancellationToken cancellationToken)\n        {\n            var userSecretsId = await _propertiesProvider.GetCommonProperties().GetEvaluatedPropertyValueAsync(UserSecretsPropertyName);\n\n            if (string.IsNullOrEmpty(userSecretsId))\n            {\n                userSecretsId = Guid.NewGuid().ToString();\n                await _propertiesProvider.GetCommonProperties().SetPropertyValueAsync(UserSecretsPropertyName, userSecretsId);\n            }\n\n            var store = new SecretStore(userSecretsId);\n            await store.LoadAsync(cancellationToken);\n            return store;\n        }\n    }\n}\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager/Properties/AssemblyInfo.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Reflection;\nusing Microsoft.VisualStudio.Shell;\n\n// required for VS to generate the pkgdef\n[assembly: AssemblyVersion(\"1.0.0.0\")]\n[assembly: ProvideCodeBase(CodeBase = @\"$PackageFolder$\\Microsoft.VisualStudio.SecretManager.dll\")]\n[assembly: ProvideBindingRedirection(\n    AssemblyName = \"Microsoft.VisualStudio.SecretManager\",\n    GenerateCodeBase = true,\n    PublicKeyToken = \"adb9793829ddae60\",\n    OldVersionLowerBound = \"0.0.0.0\",\n    OldVersionUpperBound = \"1.0.0.0\",\n    NewVersion = \"1.0.0.0\")]\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager/Resources.Designer.cs",
    "content": "// <auto-generated />\nnamespace Microsoft.VisualStudio.SecretManager\n{\n    using System.Globalization;\n    using System.Reflection;\n    using System.Resources;\n\n    internal static class Resources\n    {\n        private static readonly ResourceManager _resourceManager\n            = new ResourceManager(\"Microsoft.VisualStudio.SecretManager.Resources\", typeof(Resources).GetTypeInfo().Assembly);\n\n        /// <summary>\n        /// A secret with this name already exists.\n        /// </summary>\n        internal static string Error_SecretAlreadyExists\n        {\n            get => GetString(\"Error_SecretAlreadyExists\");\n        }\n\n        /// <summary>\n        /// Value cannot be null or an empty string.\n        /// </summary>\n        internal static string Common_StringNullOrEmpty\n        {\n            get => GetString(\"Common_StringNullOrEmpty\");\n        }\n\n        /// <summary>\n        /// Value cannot be null or an empty string.\n        /// </summary>\n        internal static string FormatCommon_StringNullOrEmpty()\n            => GetString(\"Common_StringNullOrEmpty\");\n\n        /// <summary>\n        /// Invalid character '{0}' found in the user secrets ID at index '{1}'.\n        /// </summary>\n        internal static string Error_Invalid_Character_In_UserSecrets_Id\n        {\n            get => GetString(\"Error_Invalid_Character_In_UserSecrets_Id\");\n        }\n\n        /// <summary>\n        /// Invalid character '{0}' found in the user secrets ID at index '{1}'.\n        /// </summary>\n        internal static string FormatError_Invalid_Character_In_UserSecrets_Id(object p0, object p1)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Error_Invalid_Character_In_UserSecrets_Id\"), p0, p1);\n\n        /// <summary>\n        /// Could not find 'UserSecretsIdAttribute' on assembly '{0}'.\n        /// Check that the project for '{0}' has set the 'UserSecretsId' build property.\n        /// If the 'UserSecretsId' property is already set then add a reference to the Microsoft.Extensions.Configuration.UserSecrets package.\n        /// </summary>\n        internal static string Error_Missing_UserSecretsIdAttribute\n        {\n            get => GetString(\"Error_Missing_UserSecretsIdAttribute\");\n        }\n\n        /// <summary>\n        /// Could not find 'UserSecretsIdAttribute' on assembly '{0}'.\n        /// Check that the project for '{0}' has set the 'UserSecretsId' build property.\n        /// If the 'UserSecretsId' property is already set then add a reference to the Microsoft.Extensions.Configuration.UserSecrets package.\n        /// </summary>\n        internal static string FormatError_Missing_UserSecretsIdAttribute(object p0)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Error_Missing_UserSecretsIdAttribute\"), p0);\n\n        /// <summary>\n        /// File path must be a non-empty string.\n        /// </summary>\n        internal static string Error_InvalidFilePath\n        {\n            get => GetString(\"Error_InvalidFilePath\");\n        }\n\n        /// <summary>\n        /// File path must be a non-empty string.\n        /// </summary>\n        internal static string FormatError_InvalidFilePath()\n            => GetString(\"Error_InvalidFilePath\");\n\n        /// <summary>\n        /// Could not parse the JSON file. Error on line number '{0}': '{1}'.\n        /// </summary>\n        internal static string Error_JSONParseError\n        {\n            get => GetString(\"Error_JSONParseError\");\n        }\n\n        /// <summary>\n        /// Could not parse the JSON file. Error on line number '{0}': '{1}'.\n        /// </summary>\n        internal static string FormatError_JSONParseError(object p0, object p1)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Error_JSONParseError\"), p0, p1);\n\n        /// <summary>\n        /// A duplicate key '{0}' was found.\n        /// </summary>\n        internal static string Error_KeyIsDuplicated\n        {\n            get => GetString(\"Error_KeyIsDuplicated\");\n        }\n\n        /// <summary>\n        /// A duplicate key '{0}' was found.\n        /// </summary>\n        internal static string FormatError_KeyIsDuplicated(object p0)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Error_KeyIsDuplicated\"), p0);\n\n        /// <summary>\n        /// Unsupported JSON token '{0}' was found. Path '{1}', line {2} position {3}.\n        /// </summary>\n        internal static string Error_UnsupportedJSONToken\n        {\n            get => GetString(\"Error_UnsupportedJSONToken\");\n        }\n\n        /// <summary>\n        /// Unsupported JSON token '{0}' was found. Path '{1}', line {2} position {3}.\n        /// </summary>\n        internal static string FormatError_UnsupportedJSONToken(object p0, object p1, object p2, object p3)\n            => string.Format(CultureInfo.CurrentCulture, GetString(\"Error_UnsupportedJSONToken\"), p0, p1, p2, p3);\n\n        private static string GetString(string name, params string[] formatterNames)\n        {\n            var value = _resourceManager.GetString(name);\n\n            System.Diagnostics.Debug.Assert(value != null);\n\n            if (formatterNames != null)\n            {\n                for (var i = 0; i < formatterNames.Length; i++)\n                {\n                    value = value.Replace(\"{\" + formatterNames[i] + \"}\", \"{\" + i + \"}\");\n                }\n            }\n\n            return value;\n        }\n    }\n}\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager/Resources.resx",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"Error_InvalidFilePath\" xml:space=\"preserve\">\n    <value>File path must be a non-empty string.</value>\n  </data>\n  <data name=\"Error_JSONParseError\" xml:space=\"preserve\">\n    <value>Could not parse the JSON file. Error on line number '{0}': '{1}'.</value>\n  </data>\n  <data name=\"Error_KeyIsDuplicated\" xml:space=\"preserve\">\n    <value>A duplicate key '{0}' was found.</value>\n  </data>\n  <data name=\"Error_UnsupportedJSONToken\" xml:space=\"preserve\">\n    <value>Unsupported JSON token '{0}' was found. Path '{1}', line {2} position {3}.</value>\n  </data>\n  <data name=\"Common_StringNullOrEmpty\" xml:space=\"preserve\">\n    <value>Value cannot be null or an empty string.</value>\n  </data>\n  <data name=\"Error_Invalid_Character_In_UserSecrets_Id\" xml:space=\"preserve\">\n    <value>Invalid character '{0}' found in the user secrets ID at index '{1}'.</value>\n  </data>\n  <data name=\"Error_Missing_UserSecretsIdAttribute\" xml:space=\"preserve\">\n    <value>Could not find 'UserSecretsIdAttribute' on assembly '{0}'.\nCheck that the project for '{0}' has set the 'UserSecretsId' build property.\nIf the 'UserSecretsId' property is already set then add a reference to the Microsoft.Extensions.Configuration.UserSecrets package.</value>\n  </data>\n  <data name=\"Error_SecretAlreadyExists\" xml:space=\"preserve\">\n    <value>A secret with this name already exists.</value>\n  </data>\n</root>"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager/SecretManagerFactory.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.ComponentModel.Composition;\nusing Microsoft.VisualStudio.ProjectSystem;\nusing Microsoft.VisualStudio.Shell;\n\nnamespace Microsoft.VisualStudio.SecretManager\n{\n    internal class SecretManagerFactory\n    {\n        // This is capability is set in Microsoft.Extensions.Configuration.UserSecrets\n        private const string CapabilityName = \"LocalUserSecrets\";\n\n        private readonly Lazy<ProjectLocalSecretsManager> _secretManager;\n        private readonly UnconfiguredProject _project;\n\n        [ImportingConstructor]\n        public SecretManagerFactory(UnconfiguredProject project, SVsServiceProvider vsServiceProvider)\n        {\n            _project = project;\n\n            var serviceProvider = new Lazy<IServiceProvider>(() => vsServiceProvider);\n\n            _secretManager = new Lazy<ProjectLocalSecretsManager>(() =>\n            {\n                var propertiesProvider = _project.Services.ActiveConfiguredProjectProvider.ActiveConfiguredProject.Services.ProjectPropertiesProvider;\n                return new ProjectLocalSecretsManager(propertiesProvider, serviceProvider);\n            });\n        }\n        \n        [ExportVsProfferedProjectService(typeof(SVsProjectLocalSecrets))]\n        [AppliesTo(CapabilityName)]\n        public SVsProjectLocalSecrets ProjectLocalSecretsManager => _secretManager.Value;\n    }\n}\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager/SecretStore.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Text;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Extensions.Configuration.Json;\nusing Microsoft.Extensions.Configuration.UserSecrets;\nusing Microsoft.VisualStudio.Threading;\nusing Newtonsoft.Json.Linq;\nusing Task = System.Threading.Tasks.Task;\n\nnamespace Microsoft.VisualStudio.SecretManager\n{\n    /// <summary>\n    /// Provides read and write access to the secrets.json file for local user secrets.\n    /// This is not thread-safe.\n    /// This object is meant to have a short lifetime.\n    /// When calling <see cref=\"SaveAsync(CancellationToken)\"/>, this will overwrite the secrets.json file. It does not check for concurrency issues if another process has edited this file.\n    /// </summary>\n    internal class SecretStore : IDisposable\n    {\n        private Dictionary<string, string> _secrets;\n        private string _fileDir;\n        private string _filePath;\n        private bool _isDirty;\n        private volatile bool _disposed;\n\n        public SecretStore(string userSecretsId)\n        {\n            _filePath = PathHelper.GetSecretsPathFromSecretsId(userSecretsId);\n            _fileDir = Path.GetDirectoryName(_filePath);\n        }\n\n        public IReadOnlyCollection<string> ReadOnlyKeys\n        {\n            get\n            {\n                EnsureNotDisposed();\n                return _secrets.Keys;\n            }\n        }\n\n        public IReadOnlyDictionary<string, string> Values\n        {\n            get\n            {\n                EnsureNotDisposed();\n\n                return _secrets;\n            }\n        }\n\n        public bool ContainsKey(string key)\n        {\n            EnsureNotDisposed();\n\n            return _secrets.ContainsKey(key);\n        }\n\n        public string Get(string name)\n        {\n            EnsureNotDisposed();\n\n            return _secrets[name];\n        }\n\n        public void Set(string key, string value)\n        {\n            EnsureNotDisposed();\n\n            _isDirty = true;\n            _secrets[key] = value;\n        }\n\n        public bool Remove(string key)\n        {\n            EnsureNotDisposed();\n            _isDirty = true;\n            return _secrets.Remove(key);\n        }\n\n        public async Task LoadAsync(CancellationToken cancellationToken)\n        {\n            cancellationToken.ThrowIfCancellationRequested();\n            await TaskScheduler.Default;\n\n            EnsureNotDisposed();\n\n            string text = null;\n\n            if (File.Exists(_filePath))\n            {\n                text = File.ReadAllText(_filePath);\n            }\n\n            _secrets = DeserializeJson(text);\n        }\n\n        public async Task SaveAsync(CancellationToken cancellationToken)\n        {\n            cancellationToken.ThrowIfCancellationRequested();\n            await TaskScheduler.Default;\n\n            EnsureNotDisposed();\n\n            if (!_isDirty)\n            {\n                return;\n            }\n\n            Directory.CreateDirectory(_fileDir);\n            File.WriteAllText(_filePath, Stringify(_secrets), Encoding.UTF8);\n\n            _isDirty = false;\n        }\n\n        private void EnsureNotDisposed()\n        {\n            if (_disposed)\n            {\n                throw new ObjectDisposedException(nameof(SecretStore));\n            }\n        }\n\n        private static string Stringify(Dictionary<string, string> secrets)\n        {\n            var contents = new JObject();\n            if (secrets != null)\n            {\n                foreach (var secret in secrets)\n                {\n                    contents[secret.Key] = secret.Value;\n                }\n            }\n\n            return contents.ToString();\n        }\n\n        private static Dictionary<string, string> DeserializeJson(string text)\n        {\n            if (string.IsNullOrEmpty(text))\n            {\n                return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);\n            }\n\n            using (var stream = new MemoryStream())\n            {\n                var bytes = Encoding.UTF8.GetBytes(text);\n                stream.Write(bytes, 0, bytes.Length);\n                stream.Position = 0;\n\n                // might throw FormatException if JSON is malformed.\n                var data = JsonConfigurationFileParser.Parse(stream);\n\n                return new Dictionary<string, string>(data, StringComparer.OrdinalIgnoreCase);\n            }\n        }\n        \n        public void Dispose()\n        {\n            if (_disposed) return;\n            _disposed = true;\n        }\n    }\n}\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager/Sources/ConfigurationPath.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace Microsoft.Extensions.Configuration\n{\n    /// <summary>\n    /// Utility methods and constants for manipulating Configuration paths\n    /// </summary>\n    internal static class ConfigurationPath\n    {\n        /// <summary>\n        /// The delimiter \":\" used to separate individual keys in a path.\n        /// </summary>\n        public static readonly string KeyDelimiter = \":\";\n\n        /// <summary>\n        /// Combines path segments into one path.\n        /// </summary>\n        /// <param name=\"pathSegments\">The path segments to combine.</param>\n        /// <returns>The combined path.</returns>\n        public static string Combine(params string[] pathSegments)\n        {\n            if (pathSegments == null)\n            {\n                throw new ArgumentNullException(nameof(pathSegments));\n            }\n            return string.Join(KeyDelimiter, pathSegments);\n        }\n\n        /// <summary>\n        /// Combines path segments into one path.\n        /// </summary>\n        /// <param name=\"pathSegments\">The path segments to combine.</param>\n        /// <returns>The combined path.</returns>\n        public static string Combine(IEnumerable<string> pathSegments)\n        {\n            if (pathSegments == null)\n            {\n                throw new ArgumentNullException(nameof(pathSegments));\n            }\n            return string.Join(KeyDelimiter, pathSegments);\n        }\n\n        /// <summary>\n        /// Extracts the last path segment from the path.\n        /// </summary>\n        /// <param name=\"path\">The path.</param>\n        /// <returns>The last path segment of the path.</returns>\n        public static string GetSectionKey(string path)\n        {\n            if (string.IsNullOrEmpty(path))\n            {\n                return path;\n            }\n\n            var lastDelimiterIndex = path.LastIndexOf(KeyDelimiter, StringComparison.OrdinalIgnoreCase);\n            return lastDelimiterIndex == -1 ? path : path.Substring(lastDelimiterIndex + 1);\n        }\n\n        /// <summary>\n        /// Extracts the path corresponding to the parent node for a given path.\n        /// </summary>\n        /// <param name=\"path\">The path.</param>\n        /// <returns>The original path minus the last individual segment found in it. Null if the original path corresponds to a top level node.</returns>\n        public static string GetParentPath(string path)\n        {\n            if (string.IsNullOrEmpty(path))\n            {\n                return null;\n            }\n\n            var lastDelimiterIndex = path.LastIndexOf(KeyDelimiter, StringComparison.OrdinalIgnoreCase);\n            return lastDelimiterIndex == -1 ? null : path.Substring(0, lastDelimiterIndex);\n        }\n    }\n}\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager/Sources/JsonConfigurationFileParser.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.IO;\nusing System.Linq;\nusing Microsoft.VisualStudio.SecretManager;\nusing Newtonsoft.Json;\nusing Newtonsoft.Json.Linq;\n\nnamespace Microsoft.Extensions.Configuration.Json\n{\n    internal class JsonConfigurationFileParser\n    {\n        private JsonConfigurationFileParser() { }\n\n        private readonly IDictionary<string, string> _data = new SortedDictionary<string, string>(StringComparer.OrdinalIgnoreCase);\n        private readonly Stack<string> _context = new Stack<string>();\n        private string _currentPath;\n\n        private JsonTextReader _reader;\n\n        public static IDictionary<string, string> Parse(Stream input)\n            => new JsonConfigurationFileParser().ParseStream(input);\n\n        private IDictionary<string, string> ParseStream(Stream input)\n        {\n            _data.Clear();\n            _reader = new JsonTextReader(new StreamReader(input));\n            _reader.DateParseHandling = DateParseHandling.None;\n\n            var jsonConfig = JObject.Load(_reader);\n\n            VisitJObject(jsonConfig);\n\n            return _data;\n        }\n\n        private void VisitJObject(JObject jObject)\n        {\n            foreach (var property in jObject.Properties())\n            {\n                EnterContext(property.Name);\n                VisitProperty(property);\n                ExitContext();\n            }\n        }\n\n        private void VisitProperty(JProperty property)\n        {\n            VisitToken(property.Value);\n        }\n\n        private void VisitToken(JToken token)\n        {\n            switch (token.Type)\n            {\n                case JTokenType.Object:\n                    VisitJObject(token.Value<JObject>());\n                    break;\n\n                case JTokenType.Array:\n                    VisitArray(token.Value<JArray>());\n                    break;\n\n                case JTokenType.Integer:\n                case JTokenType.Float:\n                case JTokenType.String:\n                case JTokenType.Boolean:\n                case JTokenType.Bytes:\n                case JTokenType.Raw:\n                case JTokenType.Null:\n                    VisitPrimitive(token.Value<JValue>());\n                    break;\n\n                default:\n                    throw new FormatException(Resources.FormatError_UnsupportedJSONToken(\n                        _reader.TokenType,\n                        _reader.Path,\n                        _reader.LineNumber,\n                        _reader.LinePosition));\n            }\n        }\n\n        private void VisitArray(JArray array)\n        {\n            for (int index = 0; index < array.Count; index++)\n            {\n                EnterContext(index.ToString());\n                VisitToken(array[index]);\n                ExitContext();\n            }\n        }\n\n        private void VisitPrimitive(JValue data)\n        {\n            var key = _currentPath;\n\n            if (_data.ContainsKey(key))\n            {\n                throw new FormatException(Resources.FormatError_KeyIsDuplicated(key));\n            }\n            _data[key] = data.ToString(CultureInfo.InvariantCulture);\n        }\n\n        private void EnterContext(string context)\n        {\n            _context.Push(context);\n            _currentPath = ConfigurationPath.Combine(_context.Reverse());\n        }\n\n        private void ExitContext()\n        {\n            _context.Pop();\n            _currentPath = ConfigurationPath.Combine(_context.Reverse());\n        }\n    }\n}\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager/Sources/PathHelper.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing Microsoft.VisualStudio.SecretManager;\n\nnamespace Microsoft.Extensions.Configuration.UserSecrets\n{\n    /// <summary>\n    /// Provides paths for user secrets configuration files.\n    /// </summary>\n    internal class PathHelper\n    {\n        internal const string SecretsFileName = \"secrets.json\";\n\n        /// <summary>\n        /// <para>\n        /// Returns the path to the JSON file that stores user secrets.\n        /// </para>\n        /// <para>\n        /// This uses the current user profile to locate the secrets file on disk in a location outside of source control.\n        /// </para>\n        /// </summary>\n        /// <param name=\"userSecretsId\">The user secret ID.</param>\n        /// <returns>The full path to the secret file.</returns>\n        public static string GetSecretsPathFromSecretsId(string userSecretsId)\n        {\n            if (string.IsNullOrEmpty(userSecretsId))\n            {\n                throw new ArgumentException(Resources.Common_StringNullOrEmpty, nameof(userSecretsId));\n            }\n\n            var badCharIndex = userSecretsId.IndexOfAny(Path.GetInvalidFileNameChars());\n            if (badCharIndex != -1)\n            {\n                throw new InvalidOperationException(\n                    string.Format(\n                        Resources.Error_Invalid_Character_In_UserSecrets_Id,\n                        userSecretsId[badCharIndex],\n                        badCharIndex));\n            }\n\n            var root = Environment.GetEnvironmentVariable(\"APPDATA\") ??         // On Windows it goes to %APPDATA%\\Microsoft\\UserSecrets\\\n                        Environment.GetEnvironmentVariable(\"HOME\");             // On Mac/Linux it goes to ~/.microsoft/usersecrets/\n\n            if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable(\"APPDATA\")))\n            {\n                return Path.Combine(root, \"Microsoft\", \"UserSecrets\", userSecretsId, SecretsFileName);\n            }\n            else\n            {\n                return Path.Combine(root, \".microsoft\", \"usersecrets\", userSecretsId, SecretsFileName);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<PackageManifest Version=\"2.0.0\" xmlns=\"http://schemas.microsoft.com/developer/vsx-schema/2011\" xmlns:d=\"http://schemas.microsoft.com/developer/vsx-schema-design/2011\">\n    <Metadata>\n        <Identity Id=\"Microsoft.VisualStudio.SecretManager\" Version=\"|%CurrentProject%;GetBuildVersion|\" Language=\"en-US\" Publisher=\"Microsoft\" />\n        <DisplayName>ASP.NET Core User Secrets Extension</DisplayName>\n        <PackageId>Microsoft.VisualStudio.SecretManager</PackageId>\n        <Description xml:space=\"preserve\">Enables IVsProjectSecrets for ASP.NET Core projects that use Microsoft.Extensions.Configuration.UserSecrets.</Description>\n    </Metadata>\n    <Installation AllUsers=\"true\" SystemComponent=\"true\">\n        <InstallationTarget Id=\"Microsoft.VisualStudio.Community\" Version=\"[15.0.26228.04,)\" />\n    </Installation>\n    <Dependencies>\n        <Dependency Id=\"Microsoft.Framework.NDP\" DisplayName=\"Microsoft .NET Framework\" d:Source=\"Manual\" Version=\"[4.6,)\" />\n        <Dependency Id=\"Microsoft.VisualStudio.MPF.15.0\" DisplayName=\"Visual Studio MPF 15.0\" d:Source=\"Installed\" Version=\"[15.0]\" />\n    </Dependencies>\n    <Prerequisites>\n        <Prerequisite Id=\"Microsoft.VisualStudio.Component.CoreEditor\" Version=\"[15.0,16.0)\" DisplayName=\"Visual Studio core editor\" />\n    </Prerequisites>\n    <Assets>\n        <Asset Type=\"Microsoft.VisualStudio.MefComponent\" d:Source=\"Project\" d:ProjectName=\"%CurrentProject%\" Path=\"|%CurrentProject%|\" />\n    </Assets>\n</PackageManifest>\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Microsoft.VisualStudio.SecretManager.TestExtension.csproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n    <ImportDirectoryBuildProps>False</ImportDirectoryBuildProps>\n    <ImportDirectoryBuildTargets>False</ImportDirectoryBuildTargets>\n    <GenerateUserSecretsAttribute>False</GenerateUserSecretsAttribute>\n    <UseCodebase>True</UseCodebase>\n    <SignAssembly>True</SignAssembly>\n    <AssemblyOriginatorKeyFile>..\\..\\build\\Key.snk</AssemblyOriginatorKeyFile>\n    <TreatWarningsAsErrors>True</TreatWarningsAsErrors>\n  </PropertyGroup>\n  <Import Project=\"..\\..\\version.props\" />\n  <Import Project=\"..\\..\\build\\dependencies.props\" />\n  <Import Project=\"..\\..\\build\\sources.props\" />\n  <Import Project=\"$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props\" Condition=\"Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')\" />\n  <PropertyGroup>\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\n    <Platform Condition=\" '$(Platform)' == '' \">AnyCPU</Platform>\n    <SchemaVersion>2.0</SchemaVersion>\n    <ProjectTypeGuids>{82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>\n    <ProjectGuid>{965F8820-F809-4081-9090-1AEC903F291B}</ProjectGuid>\n    <OutputType>Library</OutputType>\n    <AppDesignerFolder>Properties</AppDesignerFolder>\n    <RootNamespace>Microsoft.VisualStudio.SecretManager.TestExtension</RootNamespace>\n    <AssemblyName>Microsoft.VisualStudio.SecretManager.TestExtension</AssemblyName>\n    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>\n    <GeneratePkgDefFile>true</GeneratePkgDefFile>\n    <IncludeAssemblyInVSIXContainer>true</IncludeAssemblyInVSIXContainer>\n    <IncludeDebugSymbolsInVSIXContainer>true</IncludeDebugSymbolsInVSIXContainer>\n    <IncludeDebugSymbolsInLocalVSIXDeployment>true</IncludeDebugSymbolsInLocalVSIXDeployment>\n    <CopyBuildOutputToOutputDirectory>true</CopyBuildOutputToOutputDirectory>\n    <CopyOutputSymbolsToOutputDirectory>false</CopyOutputSymbolsToOutputDirectory>\n    <StartAction>Program</StartAction>\n    <StartProgram Condition=\"'$(DevEnvDir)' != ''\">$(DevEnvDir)devenv.exe</StartProgram>\n    <StartArguments>/rootsuffix Exp</StartArguments>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' \">\n    <DebugSymbols>true</DebugSymbols>\n    <DebugType>full</DebugType>\n    <Optimize>false</Optimize>\n    <OutputPath>bin\\Debug\\</OutputPath>\n    <DefineConstants>DEBUG;TRACE</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' \">\n    <DebugType>pdbonly</DebugType>\n    <Optimize>true</Optimize>\n    <OutputPath>bin\\Release\\</OutputPath>\n    <DefineConstants>TRACE</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n  </PropertyGroup>\n  <ItemGroup>\n    <Compile Include=\"NotifyPropertyChanged.cs\" />\n    <Compile Include=\"ProjectViewModel.cs\" />\n    <Compile Include=\"Properties\\AssemblyInfo.cs\" />\n    <Compile Include=\"RelayCommand.cs\" />\n    <Compile Include=\"SecretManagerTestWindow.cs\" />\n    <Compile Include=\"SecretManagerTestCommand.cs\" />\n    <Compile Include=\"SecretManagerTestControl.xaml.cs\">\n      <DependentUpon>SecretManagerTestControl.xaml</DependentUpon>\n    </Compile>\n    <Compile Include=\"SecretManagerTestPackage.cs\" />\n    <Compile Include=\"SecretManagerViewModel.cs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"source.extension.vsixmanifest\">\n      <SubType>Designer</SubType>\n    </None>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"app.config\" />\n    <None Include=\"Key.snk\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Page Include=\"SecretManagerTestControl.xaml\">\n      <SubType>Designer</SubType>\n      <Generator>MSBuild:Compile</Generator>\n    </Page>\n  </ItemGroup>\n  <ItemGroup>\n    <Reference Include=\"Microsoft.CSharp\" />\n    <Reference Include=\"PresentationCore\" />\n    <Reference Include=\"PresentationFramework\" />\n    <Reference Include=\"stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n      <EmbedInteropTypes>False</EmbedInteropTypes>\n    </Reference>\n    <Reference Include=\"System\" />\n    <Reference Include=\"System.ComponentModel.Composition\" />\n    <Reference Include=\"System.Data\" />\n    <Reference Include=\"System.Design\" />\n    <Reference Include=\"System.Drawing\" />\n    <Reference Include=\"System.Windows.Forms\" />\n    <Reference Include=\"System.Xaml\" />\n    <Reference Include=\"System.Xml\" />\n    <Reference Include=\"WindowsBase\" />\n  </ItemGroup>\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.VisualStudio.ComponentModelHost\" Version=\"15.0.26606\" />\n    <PackageReference Include=\"Microsoft.VisualStudio.ProjectSystem.Analyzers\" Version=\"15.3.224\" />\n    <PackageReference Include=\"Microsoft.VisualStudio.ProjectSystem.SDK.Tools\" Version=\"15.3.224\" />\n    <PackageReference Include=\"Microsoft.VisualStudio.ProjectSystem.SDK\" Version=\"15.3.224\" />\n    <PackageReference Include=\"Microsoft.VisualStudio.ProjectSystem\" Version=\"15.3.224\" />\n    <PackageReference Include=\"Microsoft.VisualStudio.Shell.Interop\">\n      <Version>7.10.6071</Version>\n    </PackageReference>\n    <PackageReference Include=\"Microsoft.VisualStudio.Shell.Interop.10.0\" Version=\"10.0.30319\" />\n    <PackageReference Include=\"Microsoft.VisualStudio.Shell.15.0\" Version=\"15.0.26606\" />\n    <PackageReference Include=\"Microsoft.VisualStudio.Shell.Embeddable\" Version=\"15.6.27002-vsuvscore\" />\n    <PackageReference Include=\"Microsoft.VisualStudio.Shell.Interop.11.0\">\n      <Version>11.0.61030</Version>\n    </PackageReference>\n    <PackageReference Include=\"Microsoft.VisualStudio.Shell.Interop.12.0\">\n      <Version>12.0.30110</Version>\n    </PackageReference>\n    <PackageReference Include=\"Microsoft.VisualStudio.Shell.Interop.15.3.DesignTime\">\n      <Version>15.0.26606</Version>\n    </PackageReference>\n    <PackageReference Include=\"Microsoft.VisualStudio.Shell.Interop.8.0\">\n      <Version>8.0.50727</Version>\n    </PackageReference>\n    <PackageReference Include=\"Microsoft.VisualStudio.Shell.Interop.9.0\">\n      <Version>9.0.30729</Version>\n    </PackageReference>\n    <PackageReference Include=\"Microsoft.VSSDK.BuildTools\" Version=\"15.1.192\" />\n    <PackageReference Include=\"System.ValueTuple\">\n      <Version>4.4.0</Version>\n    </PackageReference>\n  </ItemGroup>\n  <ItemGroup>\n    <Content Include=\"Resources\\SecretManagerTestCommand.png\" />\n    <Content Include=\"Resources\\SecretManagerTestPackage.ico\" />\n    <VSCTCompile Include=\"SecretManagerTestPackage.vsct\">\n      <ResourceName>Menus.ctmenu</ResourceName>\n    </VSCTCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <EmbeddedResource Include=\"VSPackage.resx\">\n      <MergeWithCTO>true</MergeWithCTO>\n      <ManifestResourceName>VSPackage</ManifestResourceName>\n    </EmbeddedResource>\n  </ItemGroup>\n  <Target Name=\"GetBuildVersion\" Outputs=\"$(VsixVersion)\" />\n  <Import Project=\"$(MSBuildToolsPath)\\Microsoft.CSharp.targets\" />\n  <Import Project=\"$(VSToolsPath)\\VSSDK\\Microsoft.VsSDK.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager.TestExtension/NotifyPropertyChanged.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.ComponentModel;\nusing System.Runtime.CompilerServices;\n\nnamespace Microsoft.VisualStudio.SecretManager.TestExtension\n{\n    public abstract class NotifyPropertyChanged : INotifyPropertyChanged\n    {\n        public event PropertyChangedEventHandler PropertyChanged;\n\n        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)\n        {\n            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));\n        }\n    }\n}\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager.TestExtension/ProjectViewModel.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.IO;\nusing Microsoft.VisualStudio.ProjectSystem;\n\nnamespace Microsoft.VisualStudio.SecretManager.TestExtension\n{\n    public class ProjectViewModel : NotifyPropertyChanged\n    {\n        public ProjectViewModel(UnconfiguredProject project)\n        {\n            Project = project;\n        }\n\n        internal UnconfiguredProject Project { get; }\n\n        public string ProjectName => Path.GetFileNameWithoutExtension(Project.FullPath);\n    }\n}\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Properties/AssemblyInfo.cs",
    "content": "﻿using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Information about an assembly is controlled through the following \n// set of attributes. Change these attribute values to modify the information\n// associated with an assembly.\n[assembly: AssemblyTitle(\"Microsoft.VisualStudio.SecretManager.TestExtension\")]\n[assembly: AssemblyDescription(\"\")]\n[assembly: AssemblyConfiguration(\"\")]\n[assembly: AssemblyCompany(\"\")]\n[assembly: AssemblyProduct(\"Microsoft.VisualStudio.SecretManager.TestExtension\")]\n[assembly: AssemblyCopyright(\"\")]\n[assembly: AssemblyTrademark(\"\")]\n[assembly: AssemblyCulture(\"\")]\n\n// Setting ComVisible to false makes the types in this assembly not visible \n// to COM components.  If you need to access a type in this assembly from \n// COM, set the ComVisible attribute to true on that type.\n[assembly: ComVisible(false)]\n\n// Version information for an assembly consists of the following four values:\n//\n//      Major Version\n//      Minor Version \n//      Build Number\n//      Revision\n//\n// You can specify all the values or you can default the Build and Revision Numbers \n// by using the '*' as shown below:\n// [assembly: AssemblyVersion(\"1.0.*\")]\n[assembly: AssemblyVersion(\"1.0.0.0\")]\n[assembly: AssemblyFileVersion(\"1.0.0.0\")]\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager.TestExtension/RelayCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Windows.Input;\n\nnamespace Microsoft.VisualStudio.SecretManager.TestExtension\n{\n    public class RelayCommand<T> : ICommand\n    {\n        readonly Action<T> _execute = null;\n        readonly Predicate<T> _canExecute = null;\n\n        public RelayCommand(Action<T> execute)\n            : this(execute, null)\n        {\n        }\n\n        public RelayCommand(Action<T> execute, Predicate<T> canExecute)\n        {\n            if (execute == null)\n                throw new ArgumentNullException(\"execute\");\n\n            _execute = execute;\n            _canExecute = canExecute;\n        }\n\n        public bool CanExecute(object parameter)\n        {\n            return _canExecute == null ? true : _canExecute((T)parameter);\n        }\n\n        public event EventHandler CanExecuteChanged\n        {\n            add { CommandManager.RequerySuggested += value; }\n            remove { CommandManager.RequerySuggested -= value; }\n        }\n\n        public void Execute(object parameter)\n        {\n            _execute((T)parameter);\n        }\n    }\n}\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestCommand.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.ComponentModel.Design;\nusing Microsoft.VisualStudio.Shell;\nusing Microsoft.VisualStudio.Shell.Interop;\n\nnamespace Microsoft.VisualStudio.SecretManager.TestExtension\n{\n    internal sealed class SecretManagerTestCommand\n    {\n        /// <summary>\n        /// Command ID.\n        /// </summary>\n        public const int CommandId = 0x0100;\n\n        /// <summary>\n        /// Command menu group (command set GUID).\n        /// </summary>\n        public static readonly Guid CommandSet = new Guid(\"e415a3f4-f2a8-4834-b7f7-f89844b2505c\");\n\n        /// <summary>\n        /// VS Package that provides this command, not null.\n        /// </summary>\n        private readonly Package package;\n\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"SecretManagerTestCommand\"/> class.\n        /// Adds our command handlers for menu (commands must exist in the command table file)\n        /// </summary>\n        /// <param name=\"package\">Owner package, not null.</param>\n        private SecretManagerTestCommand(Package package)\n        {\n            if (package == null)\n            {\n                throw new ArgumentNullException(\"package\");\n            }\n\n            this.package = package;\n\n            OleMenuCommandService commandService = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;\n            if (commandService != null)\n            {\n                var menuCommandID = new CommandID(CommandSet, CommandId);\n                var menuItem = new MenuCommand(this.ShowToolWindow, menuCommandID);\n                commandService.AddCommand(menuItem);\n            }\n        }\n\n        /// <summary>\n        /// Gets the instance of the command.\n        /// </summary>\n        public static SecretManagerTestCommand Instance\n        {\n            get;\n            private set;\n        }\n\n        /// <summary>\n        /// Gets the service provider from the owner package.\n        /// </summary>\n        private IServiceProvider ServiceProvider\n        {\n            get\n            {\n                return this.package;\n            }\n        }\n\n        /// <summary>\n        /// Initializes the singleton instance of the command.\n        /// </summary>\n        /// <param name=\"package\">Owner package, not null.</param>\n        public static void Initialize(Package package)\n        {\n            Instance = new SecretManagerTestCommand(package);\n        }\n\n        /// <summary>\n        /// Shows the tool window when the menu item is clicked.\n        /// </summary>\n        /// <param name=\"sender\">The event sender.</param>\n        /// <param name=\"e\">The event args.</param>\n        private void ShowToolWindow(object sender, EventArgs e)\n        {\n            // Get the instance number 0 of this tool window. This window is single instance so this instance\n            // is actually the only one.\n            // The last flag is set to true so that if the tool window does not exists it will be created.\n            ToolWindowPane window = this.package.FindToolWindow(typeof(SecretManagerTestWindow), 0, true);\n            if ((null == window) || (null == window.Frame))\n            {\n                throw new NotSupportedException(\"Cannot create tool window\");\n            }\n\n            IVsWindowFrame windowFrame = (IVsWindowFrame)window.Frame;\n            Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(windowFrame.Show());\n        }\n    }\n}\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml",
    "content": "<UserControl\n  x:Class=\"Microsoft.VisualStudio.SecretManager.TestExtension.SecretManagerTestControl\"\n  xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n  xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n  xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n  xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n  Background=\"{DynamicResource VsBrush.Window}\"\n  Foreground=\"{DynamicResource VsBrush.WindowText}\"\n  mc:Ignorable=\"d\"\n  d:DesignHeight=\"300\"\n  d:DesignWidth=\"300\">\n  <Grid>\n    <Grid.ColumnDefinitions>\n      <ColumnDefinition\n        Width=\"Auto\" />\n      <ColumnDefinition\n        Width=\"*\" />\n      <ColumnDefinition\n        Width=\"Auto\" />\n    </Grid.ColumnDefinitions>\n    <Grid.RowDefinitions>\n      <RowDefinition\n        Height=\"Auto\" />\n      <RowDefinition\n        Height=\"Auto\" />\n      <RowDefinition\n        Height=\"*\" />\n      <RowDefinition\n        Height=\"Auto\" />\n        </Grid.RowDefinitions>\n\n    <StackPanel\n      Grid.ColumnSpan=\"3\"\n      Grid.Row=\"0\"\n      Visibility=\"{Binding ErrorVisibility}\">\n      <Label Content=\"{Binding Error}\" HorizontalContentAlignment=\"Center\" Foreground=\"Red\"/>\n    </StackPanel>\n\n    <Label\n        Grid.Column=\"0\"\n        Grid.Row=\"1\"\n        Content=\"Select Project\"\n        Margin=\"5\"\n        Width=\"Auto\" />\n\n    <ComboBox\n      Grid.Column=\"1\"\n      Grid.Row=\"1\"\n      ItemsSource=\"{Binding Projects}\"\n      SelectedItem=\"{Binding SelectedProject}\"\n      DisplayMemberPath=\"ProjectName\"\n      Margin=\"5\"\n      HorizontalAlignment=\"Stretch\" />\n\n    <Button\n      Grid.Column=\"2\"\n      Grid.Row=\"1\"\n      Margin=\"5\"\n      Content=\"Refresh\"\n      Command=\"{Binding RefreshCommand}\" />\n\n    <ListView\n      Grid.ColumnSpan=\"3\"\n      Grid.Row=\"2\"\n      ItemsSource=\"{Binding Secrets}\"\n      IsEnabled=\"{Binding IsLoaded}\">\n      <ListView.View>\n        <GridView>\n          <GridViewColumn\n            Header=\"Key\"\n            DisplayMemberBinding=\"{Binding Key}\" />\n          <GridViewColumn\n            Header=\"Value\"\n            DisplayMemberBinding=\"{Binding Value}\" />\n        </GridView>\n      </ListView.View>\n    </ListView>\n\n    <StackPanel\n        Margin=\"4\"\n        Orientation=\"Horizontal\"\n        Grid.Row=\"3\">\n        <Button Padding=\"10,3\" Command=\"{Binding AddCommand}\">Add random value</Button>\n        <Button Padding=\"10,3\" Margin=\"5,0,0,0\" Command=\"{Binding SaveCommand}\">Save</Button>\n    </StackPanel>\n  </Grid>\n</UserControl>\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.VisualStudio.SecretManager.TestExtension\n{\n    using System.Diagnostics.CodeAnalysis;\n    using System.Windows;\n    using System.Windows.Controls;\n\n    /// <summary>\n    /// Interaction logic for SecretManagerTestControl.\n    /// </summary>\n    public partial class SecretManagerTestControl : UserControl\n    {\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"SecretManagerTestControl\"/> class.\n        /// </summary>\n        public SecretManagerTestControl()\n        {\n            this.InitializeComponent();\n        }\n\n        /// <summary>\n        /// Handles click on the button by displaying a message box.\n        /// </summary>\n        /// <param name=\"sender\">The event sender.</param>\n        /// <param name=\"e\">The event args.</param>\n        [SuppressMessage(\"Microsoft.Globalization\", \"CA1300:SpecifyMessageBoxOptions\", Justification = \"Sample code\")]\n        [SuppressMessage(\"StyleCop.CSharp.NamingRules\", \"SA1300:ElementMustBeginWithUpperCaseLetter\", Justification = \"Default event handler naming pattern\")]\n        private void button1_Click(object sender, RoutedEventArgs e)\n        {\n            MessageBox.Show(\n                string.Format(System.Globalization.CultureInfo.CurrentUICulture, \"Invoked '{0}'\", this.ToString()),\n                \"SecretManagerTest\");\n        }\n    }\n}\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Diagnostics.CodeAnalysis;\nusing System.Runtime.InteropServices;\nusing Microsoft.VisualStudio.Shell;\n\nnamespace Microsoft.VisualStudio.SecretManager.TestExtension\n{\n    [PackageRegistration(UseManagedResourcesOnly = true)]\n    [InstalledProductRegistration(\"#110\", \"#112\", \"1.0\", IconResourceID = 400)] // Info on this package for Help/About\n    [ProvideMenuResource(\"Menus.ctmenu\", 1)]\n    [ProvideToolWindow(typeof(SecretManagerTestWindow))]\n    [Guid(SecretManagerTestPackage.PackageGuidString)]\n    [SuppressMessage(\"StyleCop.CSharp.DocumentationRules\", \"SA1650:ElementDocumentationMustBeSpelledCorrectly\", Justification = \"pkgdef, VS and vsixmanifest are valid VS terms\")]\n    public sealed class SecretManagerTestPackage : Package\n    {\n        public const string PackageGuidString = \"7b771e3e-f599-4fde-95a9-e35019e705f7\";\n\n        protected override void Initialize()\n        {\n            SecretManagerTestCommand.Initialize(this);\n            base.Initialize();\n        }\n    }\n}\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.vsct",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<CommandTable xmlns=\"http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n\n  <!--  This is the file that defines the actual layout and type of the commands.\n        It is divided in different sections (e.g. command definition, command\n        placement, ...), with each defining a specific set of properties.\n        See the comment before each section for more details about how to\n        use it. -->\n\n  <!--  The VSCT compiler (the tool that translates this file into the binary\n        format that VisualStudio will consume) has the ability to run a preprocessor\n        on the vsct file; this preprocessor is (usually) the C++ preprocessor, so\n        it is possible to define includes and macros with the same syntax used\n        in C++ files. Using this ability of the compiler here, we include some files\n        defining some of the constants that we will use inside the file. -->\n\n  <!--This is the file that defines the IDs for all the commands exposed by VisualStudio. -->\n  <Extern href=\"stdidcmd.h\"/>\n\n  <!--This header contains the command ids for the menus provided by the shell. -->\n  <Extern href=\"vsshlids.h\"/>\n\n  <!--The Commands section is where commands, menus, and menu groups are defined.\n      This section uses a Guid to identify the package that provides the command defined inside it. -->\n  <Commands package=\"guidSecretManagerTestPackage\">\n    <!-- Inside this section we have different sub-sections: one for the menus, another\n    for the menu groups, one for the buttons (the actual commands), one for the combos\n    and the last one for the bitmaps used. Each element is identified by a command id that\n    is a unique pair of guid and numeric identifier; the guid part of the identifier is usually\n    called \"command set\" and is used to group different command inside a logically related\n    group; your package should define its own command set in order to avoid collisions\n    with command ids defined by other packages. -->\n\n    <!--Buttons section. -->\n    <!--This section defines the elements the user can interact with, like a menu command or a button\n        or combo box in a toolbar. -->\n    <Buttons>\n      <!--To define a menu group you have to specify its ID, the parent menu and its display priority.\n          The command is visible and enabled by default. If you need to change the visibility, status, etc, you can use\n          the CommandFlag node.\n          You can add more than one CommandFlag node e.g.:\n              <CommandFlag>DefaultInvisible</CommandFlag>\n              <CommandFlag>DynamicVisibility</CommandFlag>\n          If you do not want an image next to your command, remove the Icon node /> -->\n      <Button guid=\"guidSecretManagerTestPackageCmdSet\" id=\"SecretManagerTestCommandId\" priority=\"0x0100\" type=\"Button\">\n        <Parent guid=\"guidSHLMainMenu\" id=\"IDG_VS_WNDO_OTRWNDWS1\"/>\n        <Icon guid=\"guidImages\" id=\"bmpPic1\" />\n        <Strings>\n          <ButtonText>SecretManager Test</ButtonText>\n        </Strings>\n      </Button>\n    </Buttons>\n\n    <!--The bitmaps section is used to define the bitmaps that are used for the commands.-->\n    <Bitmaps>\n      <!--  The bitmap id is defined in a way that is a little bit different from the others:\n            the declaration starts with a guid for the bitmap strip, then there is the resource id of the\n            bitmap strip containing the bitmaps and then there are the numeric ids of the elements used\n            inside a button definition. An important aspect of this declaration is that the element id\n            must be the actual index (1-based) of the bitmap inside the bitmap strip. -->\n      <Bitmap guid=\"guidImages\" href=\"Resources\\SecretManagerTestCommand.png\" usedList=\"bmpPic1, bmpPic2, bmpPicSearch, bmpPicX, bmpPicArrows, bmpPicStrikethrough\"/>\n    </Bitmaps>\n  </Commands>\n\n  <Symbols>\n    <!-- This is the package guid. -->\n    <GuidSymbol name=\"guidSecretManagerTestPackage\" value=\"{7b771e3e-f599-4fde-95a9-e35019e705f7}\" />\n\n    <!-- This is the guid used to group the menu commands together -->\n    <GuidSymbol name=\"guidSecretManagerTestPackageCmdSet\" value=\"{e415a3f4-f2a8-4834-b7f7-f89844b2505c}\">\n      <IDSymbol name=\"SecretManagerTestCommandId\" value=\"0x0100\" />\n    </GuidSymbol>\n\n    <GuidSymbol name=\"guidImages\" value=\"{ab6e0ec7-5f1f-4134-a2b5-28e528fac523}\" >\n      <IDSymbol name=\"bmpPic1\" value=\"1\" />\n      <IDSymbol name=\"bmpPic2\" value=\"2\" />\n      <IDSymbol name=\"bmpPicSearch\" value=\"3\" />\n      <IDSymbol name=\"bmpPicX\" value=\"4\" />\n      <IDSymbol name=\"bmpPicArrows\" value=\"5\" />\n      <IDSymbol name=\"bmpPicStrikethrough\" value=\"6\" />\n    </GuidSymbol>\n  </Symbols>\n</CommandTable>\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestWindow.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Runtime.InteropServices;\nusing Microsoft.VisualStudio.ComponentModelHost;\nusing Microsoft.VisualStudio.ProjectSystem;\nusing Microsoft.VisualStudio.Shell;\n\nnamespace Microsoft.VisualStudio.SecretManager.TestExtension\n{\n    [Guid(\"6afffd63-17b6-4ef2-b515-fee22d767631\")]\n    public class SecretManagerTestWindow : ToolWindowPane\n    {\n        public SecretManagerTestWindow()\n            : base(null)\n        {\n            this.Caption = \"SecretManager Test Window\";\n            this.Content = new SecretManagerTestControl();\n        }\n\n        protected override void Initialize()\n        {\n            base.Initialize();\n\n            var component = (IComponentModel)GetService(typeof(SComponentModel));\n            var projectService = component.GetService<IProjectServiceAccessor>().GetProjectService();\n            ((SecretManagerTestControl)Content).DataContext = new SecretManagerViewModel(projectService);\n        }\n    }\n}\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerViewModel.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Collections.ObjectModel;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Threading.Tasks;\nusing System.Windows;\nusing Microsoft.VisualStudio.ProjectSystem;\nusing Microsoft.VisualStudio.Shell;\nusing Microsoft.VisualStudio.Shell.Interop;\nusing Microsoft.VisualStudio.Threading;\nusing IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;\nusing Task = System.Threading.Tasks.Task;\n\nnamespace Microsoft.VisualStudio.SecretManager.TestExtension\n{\n    public class SecretManagerViewModel : NotifyPropertyChanged\n    {\n        private readonly IProjectService _projectService;\n        private readonly Random _rand;\n        private string _error;\n        private bool _isLoaded;\n        private ProjectViewModel _selectedProject;\n\n        public SecretManagerViewModel(IProjectService projectService)\n        {\n            _projectService = projectService;\n\n            RefreshCommand = new RelayCommand<object>(Refresh, RefreshIsEnabled);\n            AddCommand = new RelayCommand<object>(Add, IsProjectLoaded);\n            SaveCommand = new RelayCommand<object>(Save, IsProjectLoaded);\n            Refresh(null);\n            _rand = new Random();\n        }\n\n        public RelayCommand<object> RefreshCommand { get; }\n\n        public RelayCommand<object> AddCommand { get; }\n        public RelayCommand<object> SaveCommand { get; }\n\n        public ObservableCollection<ProjectViewModel> Projects { get; } = new ObservableCollection<ProjectViewModel>();\n\n        public ProjectViewModel SelectedProject\n        {\n            get => _selectedProject;\n            set\n            {\n                if (value == _selectedProject)\n                {\n                    return;\n                }\n\n                _selectedProject = value;\n                OnSelectedProjectChanged();\n                OnPropertyChanged();\n            }\n        }\n\n        public bool IsLoaded\n        {\n            get => _isLoaded;\n            set\n            {\n                if (value == _isLoaded)\n                {\n                    return;\n                }\n\n                _isLoaded = value;\n                OnPropertyChanged();\n            }\n        }\n\n        public string Error\n        {\n            get => _error;\n            set\n            {\n                if (value == _error)\n                {\n                    return;\n                }\n\n                _error = value;\n                OnPropertyChanged();\n                OnPropertyChanged(nameof(ErrorVisibility));\n            }\n        }\n\n        public Visibility ErrorVisibility => Error == null ? Visibility.Collapsed : Visibility.Visible;\n\n        public ObservableCollection<KeyValuePair<string, string>> Secrets { get; } = new ObservableCollection<KeyValuePair<string, string>>();\n\n        private bool RefreshIsEnabled(object obj) => IsLoaded || SelectedProject == null;\n\n        private void Refresh(object obj)\n        {\n            Projects.Clear();\n\n            foreach (var project in _projectService.LoadedUnconfiguredProjects)\n            {\n                Projects.Add(new ProjectViewModel(project));\n            }\n        }\n\n        private bool IsProjectLoaded(object obj) => IsLoaded && SelectedProject != null;\n\n        private void Add(object obj)\n        {\n            Secrets.Add(new KeyValuePair<string, string>(\"NewKey\" + _rand.Next(10_000), \"My new totally random and secret test value\"));\n        }\n\n        private async void Save(object obj)\n        {\n            Exception exception;\n\n            try\n            {\n                IOleServiceProvider oleServices;\n                var project = (IVsProject)_selectedProject.Project.Services.HostObject;\n                Marshal.ThrowExceptionForHR(project.GetItemContext((uint)VSConstants.VSITEMID.Root, out oleServices));\n                var services = new ServiceProvider(oleServices);\n\n                var projectSecrets = (IVsProjectSecrets)services.GetService(typeof(SVsProjectLocalSecrets));\n                await TaskScheduler.Default;\n\n                if (projectSecrets == null)\n                {\n                    exception = null;\n                }\n                else\n                {\n                    foreach (var secret in Secrets)\n                    {\n                        await projectSecrets.SetSecretAsync(secret.Key, secret.Value).ConfigureAwait(false);\n                    }\n\n                    exception = null;\n                }\n            }\n            catch (Exception ex)\n            {\n                exception = ex;\n            }\n\n            if (exception != null)\n            {\n                Error = exception.ToString();\n            }\n        }\n\n        private async void OnSelectedProjectChanged()\n        {\n            Secrets.Clear();\n            IsLoaded = false;\n\n            if (_selectedProject == null)\n            {\n                return;\n            }\n\n            KeyValuePair<string, string>[] results;\n            Exception exception;\n\n            try\n            {\n                IOleServiceProvider oleServices;\n                var project = (IVsProject)_selectedProject.Project.Services.HostObject;\n                Marshal.ThrowExceptionForHR(project.GetItemContext((uint)VSConstants.VSITEMID.Root, out oleServices));\n                var services = new ServiceProvider(oleServices);\n\n                var projectSecrets = (IVsProjectSecrets)services.GetService(typeof(SVsProjectLocalSecrets));\n                await TaskScheduler.Default;\n\n                if (projectSecrets == null)\n                {\n                    results = null;\n                    exception = null;\n                }\n                else\n                {\n                    var secrets = await projectSecrets.GetSecretsAsync().ConfigureAwait(false);\n\n                    results = secrets.ToArray();\n                    exception = null;\n                }\n            }\n            catch (Exception ex)\n            {\n                results = null;\n                exception = ex;\n            }\n\n            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();\n\n            if (exception != null)\n            {\n                Error = exception.ToString();\n            }\n            else if (results != null)\n            {\n                for (var i = 0; i < results.Length; i++)\n                {\n                    Secrets.Add(results[i]);\n                }\n            }\n\n            IsLoaded = true;\n        }\n    }\n}\n"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager.TestExtension/VSPackage.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n    VS SDK Notes: This resx file contains the resources that will be consumed from your package by Visual Studio.\n    For example, Visual Studio will attempt to load resource '400' from this resource stream when it needs to\n    load your package's icon. Because Visual Studio will always look in the VSPackage.resources stream first for\n    resources it needs, you should put additional resources that Visual Studio will load directly into this resx\n    file.\n\n    Resources that you would like to access directly from your package in a strong-typed fashion should be stored\n    in Resources.resx or another resx file.\n-->\n<root>\n  <!--\n    Microsoft ResX Schema\n\n    Version 2.0\n\n    The primary goals of this format is to allow a simple XML format\n    that is mostly human readable. The generation and parsing of the\n    various data types are done through the TypeConverter classes\n    associated with the data types.\n\n    Example:\n\n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n\n    There are any number of \"resheader\" rows that contain simple\n    name/value pairs.\n\n    Each data row contains a name, and value. The row also contains a\n    type or mimetype. Type corresponds to a .NET class that support\n    text/value conversion through the TypeConverter architecture.\n    Classes that don't support this are serialized and stored with the\n    mimetype set.\n\n    The mimetype is used for serialized objects, and tells the\n    ResXResourceReader how to depersist the object. This is currently not\n    extensible. For a given mimetype the value must be set accordingly:\n\n    Note - application/x-microsoft.net.object.binary.base64 is the format\n    that the ResXResourceWriter will generate, however the reader can\n    read any of the formats listed below.\n\n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array\n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <assembly alias=\"System.Windows.Forms\" name=\"System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\" />\n  <data name=\"110\" xml:space=\"preserve\">\n    <value>SecretManagerTest Extension</value>\n  </data>\n  <data name=\"112\" xml:space=\"preserve\">\n    <value>SecretManagerTest Visual Studio Extension Detailed Info</value>\n  </data>\n  <data name=\"400\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>Resources\\SecretManagerTestPackage.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>\n  </data>\n</root>"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager.TestExtension/app.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n  <runtime>\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Collections.Immutable\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-1.2.2.0\" newVersion=\"1.2.2.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"Microsoft.VisualStudio.Validation\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-15.3.0.0\" newVersion=\"15.3.0.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Composition.AttributedModel\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-1.0.32.0\" newVersion=\"1.0.32.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Threading.Tasks.Dataflow\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.6.2.0\" newVersion=\"4.6.2.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Composition.Runtime\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-1.0.32.0\" newVersion=\"1.0.32.0\" />\n      </dependentAssembly>\n    </assemblyBinding>\n  </runtime>\n</configuration>"
  },
  {
    "path": "tooling/Microsoft.VisualStudio.SecretManager.TestExtension/source.extension.vsixmanifest",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<PackageManifest Version=\"2.0.0\" xmlns=\"http://schemas.microsoft.com/developer/vsx-schema/2011\" xmlns:d=\"http://schemas.microsoft.com/developer/vsx-schema-design/2011\">\n    <Metadata>\n        <Identity Id=\"Microsoft.VisualStudio.SecretManager.TestExtension\" Version=\"|%CurrentProject%;GetBuildVersion|\" Language=\"en-US\" Publisher=\"Microsoft\" />\n        <DisplayName>Microsoft.VisualStudio.SecretManager.TestExtension</DisplayName>\n        <Description xml:space=\"preserve\">A test extension for Microsoft.VisualStudio.TestExtension</Description>\n    </Metadata>\n    <Installation>\n        <InstallationTarget Id=\"Microsoft.VisualStudio.Community\" Version=\"[15.0]\" />\n    </Installation>\n    <Dependencies>\n        <Dependency Id=\"Microsoft.Framework.NDP\" DisplayName=\"Microsoft .NET Framework\" d:Source=\"Manual\" Version=\"[4.5,)\" />\n        <Dependency Id=\"Microsoft.VisualStudio.MPF.15.0\" DisplayName=\"Visual Studio MPF 15.0\" d:Source=\"Installed\" Version=\"[15.0]\" />\n    </Dependencies>\n    <Prerequisites>\n        <Prerequisite Id=\"Microsoft.VisualStudio.Component.CoreEditor\" Version=\"[15.0,16.0)\" DisplayName=\"Visual Studio core editor\" />\n    </Prerequisites>\n    <Assets>\n        <Asset Type=\"Microsoft.VisualStudio.VsPackage\" d:Source=\"Project\" d:ProjectName=\"%CurrentProject%\" Path=\"|%CurrentProject%;PkgdefProjectOutputGroup|\" />\n    </Assets>\n</PackageManifest>\n"
  },
  {
    "path": "version.props",
    "content": "﻿<Project>\n  <PropertyGroup>\n    <VersionPrefix>3.0.0</VersionPrefix>\n    <VsixVersion>16.0</VsixVersion>\n    <VersionSuffix>alpha1</VersionSuffix>\n    <PackageVersion Condition=\"'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' == 'rtm' \">$(VersionPrefix)</PackageVersion>\n    <PackageVersion Condition=\"'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' != 'rtm' \">$(VersionPrefix)-$(VersionSuffix)-final</PackageVersion>\n    <VsixVersion Condition=\"'$(BuildNumber)' != ''\">$(VsixVersion).$(BuildNumber)</VsixVersion>\n    <VsixVersion Condition=\"'$(BuildNumber)' == ''\">$(VsixVersion).999999</VsixVersion>\n    <BuildNumber Condition=\"'$(BuildNumber)' == ''\">t000</BuildNumber>\n    <FeatureBranchVersionPrefix Condition=\"'$(FeatureBranchVersionPrefix)' == ''\">a-</FeatureBranchVersionPrefix>\n    <VersionSuffix Condition=\"'$(VersionSuffix)' != '' And '$(FeatureBranchVersionSuffix)' != ''\">$(FeatureBranchVersionPrefix)$(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\\w-]', '-'))</VersionSuffix>\n    <VersionSuffix Condition=\"'$(VersionSuffix)' != '' And '$(BuildNumber)' != ''\">$(VersionSuffix)-$(BuildNumber)</VersionSuffix>\n  </PropertyGroup>\n</Project>\n"
  }
]