Reorganize source code in preparation to move into aspnet/AspNetCore
Prior to reorganization, this source code was found in a24b4ee459
This commit is contained in:
commit
f1e60a8083
|
|
@ -1,17 +0,0 @@
|
||||||
init:
|
|
||||||
- git config --global core.autocrlf true
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
- /^release\/.*$/
|
|
||||||
- /^(.*\/)?ci-.*$/
|
|
||||||
build_script:
|
|
||||||
- ps: .\run.ps1 default-build
|
|
||||||
clone_depth: 1
|
|
||||||
environment:
|
|
||||||
global:
|
|
||||||
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
|
|
||||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
|
||||||
test: 'off'
|
|
||||||
deploy: 'off'
|
|
||||||
os: Visual Studio 2017
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
# EditorConfig is awesome:http://EditorConfig.org
|
|
||||||
|
|
||||||
# top-most EditorConfig file
|
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
indent_style = space
|
|
||||||
charset = utf-8
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
insert_final_newline = true
|
|
||||||
|
|
||||||
[*.cs]
|
|
||||||
indent_size = 4
|
|
||||||
dotnet_sort_system_directives_first = true:warning
|
|
||||||
|
|
||||||
# Xml files
|
|
||||||
[*.{csproj,config,props,targets,ruleset,config,resx,xml}]
|
|
||||||
indent_size = 2
|
|
||||||
|
|
||||||
[*.{json, yml}]
|
|
||||||
indent_size = 2
|
|
||||||
|
|
||||||
[*.{ps1,sh}]
|
|
||||||
indent_size = 4
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
*.doc diff=astextplain
|
|
||||||
*.DOC diff=astextplain
|
|
||||||
*.docx diff=astextplain
|
|
||||||
*.DOCX diff=astextplain
|
|
||||||
*.dot diff=astextplain
|
|
||||||
*.DOT diff=astextplain
|
|
||||||
*.pdf diff=astextplain
|
|
||||||
*.PDF diff=astextplain
|
|
||||||
*.rtf diff=astextplain
|
|
||||||
*.RTF diff=astextplain
|
|
||||||
|
|
||||||
*.jpg binary
|
|
||||||
*.png binary
|
|
||||||
*.gif binary
|
|
||||||
|
|
||||||
*.cs text=auto diff=csharp
|
|
||||||
*.vb text=auto
|
|
||||||
*.resx text=auto
|
|
||||||
*.c text=auto
|
|
||||||
*.cpp text=auto
|
|
||||||
*.cxx text=auto
|
|
||||||
*.h text=auto
|
|
||||||
*.hxx text=auto
|
|
||||||
*.py text=auto
|
|
||||||
*.rb text=auto
|
|
||||||
*.java text=auto
|
|
||||||
*.html text=auto
|
|
||||||
*.htm text=auto
|
|
||||||
*.css text=auto
|
|
||||||
*.scss text=auto
|
|
||||||
*.sass text=auto
|
|
||||||
*.less text=auto
|
|
||||||
*.js text=auto
|
|
||||||
*.lisp text=auto
|
|
||||||
*.clj text=auto
|
|
||||||
*.sql text=auto
|
|
||||||
*.php text=auto
|
|
||||||
*.lua text=auto
|
|
||||||
*.m text=auto
|
|
||||||
*.asm text=auto
|
|
||||||
*.erl text=auto
|
|
||||||
*.fs text=auto
|
|
||||||
*.fsx text=auto
|
|
||||||
*.hs text=auto
|
|
||||||
|
|
||||||
*.csproj text=auto
|
|
||||||
*.vbproj text=auto
|
|
||||||
*.fsproj text=auto
|
|
||||||
*.dbproj text=auto
|
|
||||||
*.sln text=auto eol=crlf
|
|
||||||
|
|
||||||
*.sh eol=lf
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
[Oo]bj/
|
|
||||||
[Bb]in/
|
|
||||||
TestResults/
|
|
||||||
.nuget/
|
|
||||||
_ReSharper.*/
|
|
||||||
packages/
|
|
||||||
artifacts/
|
|
||||||
PublishProfiles/
|
|
||||||
*.user
|
|
||||||
*.suo
|
|
||||||
*.cache
|
|
||||||
*.docstates
|
|
||||||
_ReSharper.*
|
|
||||||
nuget.exe
|
|
||||||
*net45.csproj
|
|
||||||
*net451.csproj
|
|
||||||
*k10.csproj
|
|
||||||
*.psess
|
|
||||||
*.vsp
|
|
||||||
*.pidb
|
|
||||||
*.userprefs
|
|
||||||
*DS_Store
|
|
||||||
*.ncrunchsolution
|
|
||||||
*.*sdf
|
|
||||||
*.ipch
|
|
||||||
*.sln.ide
|
|
||||||
project.lock.json
|
|
||||||
.testPublish/
|
|
||||||
.build/
|
|
||||||
/.vs/
|
|
||||||
.vscode/
|
|
||||||
*.nuget.props
|
|
||||||
*.nuget.targets
|
|
||||||
.idea/
|
|
||||||
.dotnet/
|
|
||||||
global.json
|
|
||||||
*.binlog
|
|
||||||
27
.travis.yml
27
.travis.yml
|
|
@ -1,27 +0,0 @@
|
||||||
language: csharp
|
|
||||||
sudo: false
|
|
||||||
dist: trusty
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
|
|
||||||
- DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
|
||||||
mono: none
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- osx
|
|
||||||
osx_image: xcode8.2
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libunwind8
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
- /^release\/.*$/
|
|
||||||
- /^(.*\/)?ci-.*$/
|
|
||||||
before_install:
|
|
||||||
- if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s
|
|
||||||
/usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib
|
|
||||||
/usr/local/lib/; fi
|
|
||||||
script:
|
|
||||||
- ./build.sh
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
trigger:
|
|
||||||
- master
|
|
||||||
- release/*
|
|
||||||
|
|
||||||
resources:
|
|
||||||
repositories:
|
|
||||||
- repository: buildtools
|
|
||||||
type: git
|
|
||||||
name: aspnet-BuildTools
|
|
||||||
ref: refs/heads/master
|
|
||||||
|
|
||||||
phases:
|
|
||||||
- template: .vsts-pipelines/templates/project-ci.yml@buildtools
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
trigger:
|
|
||||||
- master
|
|
||||||
- release/*
|
|
||||||
|
|
||||||
# See https://github.com/aspnet/BuildTools
|
|
||||||
resources:
|
|
||||||
repositories:
|
|
||||||
- repository: buildtools
|
|
||||||
type: github
|
|
||||||
endpoint: DotNet-Bot GitHub Connection
|
|
||||||
name: aspnet/BuildTools
|
|
||||||
ref: refs/heads/master
|
|
||||||
|
|
||||||
phases:
|
|
||||||
- template: .vsts-pipelines/templates/project-ci.yml@buildtools
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
Contributing
|
|
||||||
======
|
|
||||||
|
|
||||||
Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/master/CONTRIBUTING.md) in the Home repo.
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
<Project>
|
|
||||||
<Import
|
|
||||||
Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), AspNetCoreSettings.props))\AspNetCoreSettings.props"
|
|
||||||
Condition=" '$(CI)' != 'true' AND '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), AspNetCoreSettings.props))' != '' " />
|
|
||||||
|
|
||||||
<Import Project="version.props" />
|
|
||||||
<Import Project="build\dependencies.props" />
|
|
||||||
<Import Project="build\sources.props" />
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<Product>Microsoft .NET</Product>
|
|
||||||
<RepositoryUrl>https://github.com/aspnet/DotNetTools</RepositoryUrl>
|
|
||||||
<RepositoryType>git</RepositoryType>
|
|
||||||
<RepositoryRoot>$(MSBuildThisFileDirectory)</RepositoryRoot>
|
|
||||||
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)build\Key.snk</AssemblyOriginatorKeyFile>
|
|
||||||
<SignAssembly>true</SignAssembly>
|
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
|
||||||
|
|
||||||
<!-- Binary compatiblity is not a goal for command-line tools. -->
|
|
||||||
<EnableApiCheck>false</EnableApiCheck>
|
|
||||||
<BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\</BaseIntermediateOutputPath>
|
|
||||||
<BaseOutputPath>$(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\</BaseOutputPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.0' ">$(MicrosoftNETCoreApp30PackageVersion)</RuntimeFrameworkVersion>
|
|
||||||
<NETStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard2.0' ">$(NETStandardLibrary20PackageVersion)</NETStandardImplicitPackageVersion>
|
|
||||||
<!-- aspnet/BuildTools#662 Don't police what version of NetCoreApp we use -->
|
|
||||||
<NETCoreAppMaximumVersion>99.9</NETCoreAppMaximumVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
206
DotNetTools.sln
206
DotNetTools.sln
|
|
@ -1,206 +0,0 @@
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio 15
|
|
||||||
VisualStudioVersion = 15.0.27120.0
|
|
||||||
MinimumVisualStudioVersion = 15.0.26730.03
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}"
|
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
src\Directory.Build.props = src\Directory.Build.props
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-watch", "src\dotnet-watch\dotnet-watch.csproj", "{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8321E0D1-9A47-4D2F-AED8-3AE636D44E35}"
|
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
.appveyor.yml = .appveyor.yml
|
|
||||||
.editorconfig = .editorconfig
|
|
||||||
.gitattributes = .gitattributes
|
|
||||||
.gitignore = .gitignore
|
|
||||||
.travis.yml = .travis.yml
|
|
||||||
build.cmd = build.cmd
|
|
||||||
build.ps1 = build.ps1
|
|
||||||
build.sh = build.sh
|
|
||||||
CONTRIBUTING.md = CONTRIBUTING.md
|
|
||||||
build\dependencies.props = build\dependencies.props
|
|
||||||
Directory.Build.props = Directory.Build.props
|
|
||||||
Directory.Build.targets = Directory.Build.targets
|
|
||||||
LICENSE.txt = LICENSE.txt
|
|
||||||
NuGet.config = NuGet.config
|
|
||||||
NuGetPackageVerifier.json = NuGetPackageVerifier.json
|
|
||||||
README.md = README.md
|
|
||||||
build\sources.props = build\sources.props
|
|
||||||
version.props = version.props
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F5B382BC-258F-46E1-AC3D-10E5CCD55134}"
|
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
test\Directory.Build.props = test\Directory.Build.props
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-watch.FunctionalTests", "test\dotnet-watch.FunctionalTests\dotnet-watch.FunctionalTests.csproj", "{16BADE2F-1184-4518-8A70-B68A19D0805B}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-user-secrets", "src\dotnet-user-secrets\dotnet-user-secrets.csproj", "{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-user-secrets.Tests", "test\dotnet-user-secrets.Tests\dotnet-user-secrets.Tests.csproj", "{7B331122-83B1-4F08-A119-DC846959844C}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-watch.Tests", "test\dotnet-watch.Tests\dotnet-watch.Tests.csproj", "{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-sql-cache", "src\dotnet-sql-cache\dotnet-sql-cache.csproj", "{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-dev-certs", "src\dotnet-dev-certs\dotnet-dev-certs.csproj", "{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.VisualStudio.SecretManager", "tooling\Microsoft.VisualStudio.SecretManager\Microsoft.VisualStudio.SecretManager.csproj", "{5E117F2E-7152-447F-BF47-59F759EEF3A7}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tooling", "tooling", "{62826851-7D74-4F1E-B7D1-12553B789CD8}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.VisualStudio.SecretManager.TestExtension", "tooling\Microsoft.VisualStudio.SecretManager.TestExtension\Microsoft.VisualStudio.SecretManager.TestExtension.csproj", "{965F8820-F809-4081-9090-1AEC903F291B}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DeveloperCertificates.XPlat", "src\Microsoft.AspNetCore.DeveloperCertificates.XPlat\Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj", "{96E71881-1465-44F5-B4B7-DF9B370FFD02}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.HttpRepl", "src\Microsoft.HttpRepl\Microsoft.HttpRepl.csproj", "{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Repl", "src\Microsoft.Repl\Microsoft.Repl.csproj", "{EE9A6128-3DE2-4206-A5A4-3ED935084590}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Repl.Tests", "test\Microsoft.Repl.Tests\Microsoft.Repl.Tests.csproj", "{59C2B354-3B5E-40EB-A7BC-74583A5707CA}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.HttpRepl.Tests", "test\Microsoft.HttpRepl.Tests\Microsoft.HttpRepl.Tests.csproj", "{BE7CC4CD-CD76-4211-B593-CAC84407162A}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
DebugNoVSIX|Any CPU = DebugNoVSIX|Any CPU
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
ReleaseNoVSIX|Any CPU = ReleaseNoVSIX|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{16BADE2F-1184-4518-8A70-B68A19D0805B}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{16BADE2F-1184-4518-8A70-B68A19D0805B}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{16BADE2F-1184-4518-8A70-B68A19D0805B}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{16BADE2F-1184-4518-8A70-B68A19D0805B}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{7B331122-83B1-4F08-A119-DC846959844C}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{7B331122-83B1-4F08-A119-DC846959844C}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{7B331122-83B1-4F08-A119-DC846959844C}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{7B331122-83B1-4F08-A119-DC846959844C}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{5E117F2E-7152-447F-BF47-59F759EEF3A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{5E117F2E-7152-447F-BF47-59F759EEF3A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{5E117F2E-7152-447F-BF47-59F759EEF3A7}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{5E117F2E-7152-447F-BF47-59F759EEF3A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{5E117F2E-7152-447F-BF47-59F759EEF3A7}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{5E117F2E-7152-447F-BF47-59F759EEF3A7}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{965F8820-F809-4081-9090-1AEC903F291B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{965F8820-F809-4081-9090-1AEC903F291B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{965F8820-F809-4081-9090-1AEC903F291B}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{965F8820-F809-4081-9090-1AEC903F291B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{965F8820-F809-4081-9090-1AEC903F291B}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{965F8820-F809-4081-9090-1AEC903F291B}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{96E71881-1465-44F5-B4B7-DF9B370FFD02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{96E71881-1465-44F5-B4B7-DF9B370FFD02}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{96E71881-1465-44F5-B4B7-DF9B370FFD02}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{96E71881-1465-44F5-B4B7-DF9B370FFD02}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{96E71881-1465-44F5-B4B7-DF9B370FFD02}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{96E71881-1465-44F5-B4B7-DF9B370FFD02}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{96E71881-1465-44F5-B4B7-DF9B370FFD02}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{96E71881-1465-44F5-B4B7-DF9B370FFD02}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{EE9A6128-3DE2-4206-A5A4-3ED935084590}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{EE9A6128-3DE2-4206-A5A4-3ED935084590}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{EE9A6128-3DE2-4206-A5A4-3ED935084590}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{EE9A6128-3DE2-4206-A5A4-3ED935084590}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{EE9A6128-3DE2-4206-A5A4-3ED935084590}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{EE9A6128-3DE2-4206-A5A4-3ED935084590}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{EE9A6128-3DE2-4206-A5A4-3ED935084590}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{EE9A6128-3DE2-4206-A5A4-3ED935084590}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{59C2B354-3B5E-40EB-A7BC-74583A5707CA}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{BE7CC4CD-CD76-4211-B593-CAC84407162A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{BE7CC4CD-CD76-4211-B593-CAC84407162A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{BE7CC4CD-CD76-4211-B593-CAC84407162A}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{BE7CC4CD-CD76-4211-B593-CAC84407162A}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{BE7CC4CD-CD76-4211-B593-CAC84407162A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{BE7CC4CD-CD76-4211-B593-CAC84407162A}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{BE7CC4CD-CD76-4211-B593-CAC84407162A}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{BE7CC4CD-CD76-4211-B593-CAC84407162A}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(NestedProjects) = preSolution
|
|
||||||
{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46} = {66517987-2A5A-4330-B130-207039378FD4}
|
|
||||||
{16BADE2F-1184-4518-8A70-B68A19D0805B} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134}
|
|
||||||
{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E} = {66517987-2A5A-4330-B130-207039378FD4}
|
|
||||||
{7B331122-83B1-4F08-A119-DC846959844C} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134}
|
|
||||||
{8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134}
|
|
||||||
{53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4}
|
|
||||||
{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8} = {66517987-2A5A-4330-B130-207039378FD4}
|
|
||||||
{5E117F2E-7152-447F-BF47-59F759EEF3A7} = {62826851-7D74-4F1E-B7D1-12553B789CD8}
|
|
||||||
{965F8820-F809-4081-9090-1AEC903F291B} = {62826851-7D74-4F1E-B7D1-12553B789CD8}
|
|
||||||
{96E71881-1465-44F5-B4B7-DF9B370FFD02} = {66517987-2A5A-4330-B130-207039378FD4}
|
|
||||||
{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D} = {66517987-2A5A-4330-B130-207039378FD4}
|
|
||||||
{EE9A6128-3DE2-4206-A5A4-3ED935084590} = {66517987-2A5A-4330-B130-207039378FD4}
|
|
||||||
{59C2B354-3B5E-40EB-A7BC-74583A5707CA} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134}
|
|
||||||
{BE7CC4CD-CD76-4211-B593-CAC84407162A} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134}
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {57C07F14-2EAC-44FF-A277-B9221B4B2BF7}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
201
LICENSE.txt
201
LICENSE.txt
|
|
@ -1,201 +0,0 @@
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright (c) .NET Foundation and Contributors
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<configuration>
|
|
||||||
<packageSources>
|
|
||||||
<clear />
|
|
||||||
<!-- Restore sources should be defined in build/sources.props. -->
|
|
||||||
</packageSources>
|
|
||||||
</configuration>
|
|
||||||
40
README.md
40
README.md
|
|
@ -1,40 +0,0 @@
|
||||||
DotNetTools
|
|
||||||
===========
|
|
||||||
|
|
||||||
[](https://travis-ci.org/aspnet/DotNetTools/branches)
|
|
||||||
[](https://ci.appveyor.com/project/aspnetci/DotNetTools/branch/dev)
|
|
||||||
|
|
||||||
This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at <https://docs.asp.net>.
|
|
||||||
|
|
||||||
## Projects
|
|
||||||
|
|
||||||
The repository contains command-line tools for ASP.NET Core that are bundled* in the [.NET Core CLI](https://github.com/dotnet/cli).
|
|
||||||
Follow the links below for more details on each tool.
|
|
||||||
|
|
||||||
- [dotnet-watch](src/dotnet-watch/README.md)
|
|
||||||
- [dotnet-user-secrets](src/dotnet-user-secrets/README.md)
|
|
||||||
- [dotnet-sql-cache](src/dotnet-sql-cache/README.md)
|
|
||||||
- [dotnet-dev-certs](src/dotnet-dev-certs/README.md)
|
|
||||||
|
|
||||||
*\*This applies to .NET Core CLI 2.1.300-preview2 and up. For earlier versions of the CLI, these tools must be installed separately.*
|
|
||||||
|
|
||||||
*For 2.0 CLI and earlier, see <https://github.com/aspnet/DotNetTools/tree/rel/2.0.0/README.md> for details.*
|
|
||||||
|
|
||||||
*For 2.1.300-preview1 CLI, see <https://github.com/aspnet/DotNetTools/tree/2.1.0-preview1-final/README.md> for details.*
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
The command line tools can be invoked as a subcommand of `dotnet`.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
dotnet watch
|
|
||||||
dotnet user-secrets
|
|
||||||
dotnet sql-cache
|
|
||||||
dotnet dev-certs
|
|
||||||
```
|
|
||||||
|
|
||||||
Add `--help` to see more details. For example,
|
|
||||||
|
|
||||||
```
|
|
||||||
dotnet watch --help
|
|
||||||
```
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
@ECHO OFF
|
|
||||||
PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE"
|
|
||||||
8
build.sh
8
build.sh
|
|
@ -1,8 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
# Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs)
|
|
||||||
chmod +x "$DIR/run.sh"; sync
|
|
||||||
"$DIR/run.sh" default-build "$@"
|
|
||||||
BIN
build/Key.snk
BIN
build/Key.snk
Binary file not shown.
|
|
@ -1,9 +0,0 @@
|
||||||
<!--
|
|
||||||
Workaround for https://github.com/dotnet/project-system/issues/2129 - VS does not support using MSBuild variables for PackageReference items.
|
|
||||||
Using a variable breaks a bunch of stuff, so this file is injected into the VSIX csproj only when building on commandline.
|
|
||||||
-->
|
|
||||||
<Project ToolsVersion="15.0">
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="$(VisualStudio_NewtonsoftJsonPackageVersion)" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<!-- Don't build the VSIX by default in this branch anymore. You can still build the fix by adding /p:BuildVSIX=true. -->
|
|
||||||
<BuildVSIX Condition="'$(BuildVSIX)' ==''">false</BuildVSIX>
|
|
||||||
<RestoreDependsOn Condition="'$(OS)'=='Windows_NT' AND '$(BuildVSIX)' == 'true'">$(RestoreDependsOn);RestoreVSIX</RestoreDependsOn>
|
|
||||||
<PackageDependsOn Condition="'$(OS)'=='Windows_NT' AND '$(BuildVSIX)' == 'true'">$(PackageDependsOn);PackageVSIX</PackageDependsOn>
|
|
||||||
<GetArtifactInfoDependsOn Condition="'$(OS)'=='Windows_NT' AND '$(BuildVSIX)' == 'true'">$(GetArtifactInfoDependsOn);GetVSIXArtifactInfo</GetArtifactInfoDependsOn>
|
|
||||||
<VSIXName>Microsoft.VisualStudio.SecretManager</VSIXName>
|
|
||||||
<VSIXProject>$(RepositoryRoot)tooling\$(VSIXName)\$(VSIXName).csproj</VSIXProject>
|
|
||||||
<VSIXOutputPath>$(BuildDir)$(VSIXName).vsix</VSIXOutputPath>
|
|
||||||
<VSIXManifestOutputPath>$(BuildDir)$(VSIXName).json</VSIXManifestOutputPath>
|
|
||||||
<VSIXSymbolsOutputPath>$(BuildDir)$(VSIXName).pdb</VSIXSymbolsOutputPath>
|
|
||||||
<VSIXArtifactCategory>shipoob</VSIXArtifactCategory>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<Target
|
|
||||||
Name="GenerateVSIX"
|
|
||||||
DependsOnTargets="RestoreVSIX;PackageVSIX"
|
|
||||||
Condition="'$(OS)'=='Windows_NT'" />
|
|
||||||
|
|
||||||
<Target Name="GetVSIXArtifactInfo">
|
|
||||||
<ItemGroup>
|
|
||||||
<ArtifactInfo Include="$(VSIXOutputPath)">
|
|
||||||
<ArtifactType>VsixPackage</ArtifactType>
|
|
||||||
<Version>$(PackageVersion)</Version>
|
|
||||||
<Category>$(VSIXArtifactCategory)</Category>
|
|
||||||
<PackageId>$(VSIXName)</PackageId>
|
|
||||||
</ArtifactInfo>
|
|
||||||
|
|
||||||
<ArtifactInfo Include="$(VSIXManifestOutputPath)">
|
|
||||||
<ArtifactType>VsixPackageManifestFile</ArtifactType>
|
|
||||||
<Category>$(VSIXArtifactCategory)</Category>
|
|
||||||
<Dependencies>$(VSIXName).vsix</Dependencies>
|
|
||||||
<PackageId>$(VSIXName)</PackageId>
|
|
||||||
</ArtifactInfo>
|
|
||||||
|
|
||||||
<ArtifactInfo Include="$(VSIXSymbolsOutputPath)">
|
|
||||||
<ArtifactType>SymbolsFile</ArtifactType>
|
|
||||||
<Category>$(VSIXArtifactCategory)</Category>
|
|
||||||
<Dependencies>$(VSIXName).vsix</Dependencies>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
</ArtifactInfo>
|
|
||||||
|
|
||||||
<FilesToSign Include="$(VSIXOutputPath)" Certificate="$(VsixSigningCertName)" IsContainer="true" />
|
|
||||||
<FilesToSign Include="$(RepositoryRoot)tooling/Microsoft.VisualStudio.SecretManager/bin/$(Configuration)/Microsoft.VisualStudio.SecretManager.dll" Certificate="$(AssemblySigningCertName)" />
|
|
||||||
<FilesToExcludeFromSigning Include="$(VSIXManifestOutputPath)" />
|
|
||||||
<FilesToExcludeFromSigning Include="$(VSIXSymbolsOutputPath)" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
VisualStudioMSBuildx86Path is set by the GetToolsets target in KoreBuild if a version of VS matching the requirements in korebuild.json is found.
|
|
||||||
-->
|
|
||||||
<Target Name="RestoreVSIX" DependsOnTargets="GetToolsets">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<VSIXResponseFilePath>$(LogOutputDir)vsix-restore.rsp</VSIXResponseFilePath>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<MSBuildArguments Remove="@(MSBuildArguments)" />
|
|
||||||
<MSBuildArguments Include="
|
|
||||||
$(VSIXProject);
|
|
||||||
/t:Restore;
|
|
||||||
/m;
|
|
||||||
/v:m;
|
|
||||||
/p:Configuration=$(Configuration);
|
|
||||||
/p:BuildNumber=$(BuildNumber);
|
|
||||||
/p:PackageReferencePropsPath=$(MSBuildThisFileDirectory)VSIX.props;" />
|
|
||||||
<MSBuildArguments Include="/p:DotNetPackageVersionPropsPath=$(DotNetPackageVersionPropsPath)" Condition="'$(DotNetPackageVersionPropsPath)' != ''" />
|
|
||||||
<MSBuildArguments Include="/p:DotNetRestoreSourcePropsPath=$(DotNetRestoreSourcePropsPath)" Condition="'$(DotNetRestoreSourcePropsPath)' != ''" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<MakeDir Directories="$(LogOutputDir)" />
|
|
||||||
|
|
||||||
<WriteLinesToFile
|
|
||||||
File="$(VSIXResponseFilePath)"
|
|
||||||
Lines="@(MSBuildArguments)"
|
|
||||||
Overwrite="true" />
|
|
||||||
|
|
||||||
<Exec Command=""$(VisualStudioMSBuildx86Path)" @"$(VSIXResponseFilePath)""
|
|
||||||
Condition="'$(VisualStudioMSBuildx86Path)' != ''" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<Target Name="PackageVSIX" DependsOnTargets="GetToolsets">
|
|
||||||
|
|
||||||
<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."
|
|
||||||
Condition="'$(VisualStudioMSBuildx86Path)' == ''" />
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<VSIXLogFilePath>$(LogOutputDir)vsix.log</VSIXLogFilePath>
|
|
||||||
<VSIXResponseFilePath>$(LogOutputDir)vsix-build.rsp</VSIXResponseFilePath>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<MSBuildArguments Remove="@(MSBuildArguments)" />
|
|
||||||
<MSBuildArguments Include="
|
|
||||||
$(VSIXProject);
|
|
||||||
/m;
|
|
||||||
/v:M;
|
|
||||||
/fl;
|
|
||||||
/flp:LogFile=$(VSIXLogFilePath);
|
|
||||||
/p:DeployExtension=false;
|
|
||||||
/p:TargetVSIXContainer=$(VSIXOutputPath);
|
|
||||||
/p:Configuration=$(Configuration);
|
|
||||||
/p:SymbolsPublishDir=$(BuildDir);
|
|
||||||
/p:PackageReferencePropsPath=$(MSBuildThisFileDirectory)VSIX.props;" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<MakeDir Directories="$(LogOutputDir)" />
|
|
||||||
|
|
||||||
<WriteLinesToFile
|
|
||||||
File="$(VSIXResponseFilePath)"
|
|
||||||
Lines="@(MSBuildArguments)"
|
|
||||||
Overwrite="true" />
|
|
||||||
|
|
||||||
<Exec Command=""$(VisualStudioMSBuildx86Path)" @"$(VSIXResponseFilePath)""
|
|
||||||
Condition="'$(VisualStudioMSBuildx86Path)' != ''" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Label="Package Versions">
|
|
||||||
<InternalAspNetCoreSdkPackageVersion>3.0.0-alpha1-20181026.5</InternalAspNetCoreSdkPackageVersion>
|
|
||||||
<MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>3.0.0-alpha1-10657</MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>
|
|
||||||
<MicrosoftAspNetCoreTestingPackageVersion>3.0.0-alpha1-10657</MicrosoftAspNetCoreTestingPackageVersion>
|
|
||||||
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>3.0.0-alpha1-10657</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
|
|
||||||
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>3.0.0-alpha1-10664</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
|
|
||||||
<MicrosoftExtensionsProcessSourcesPackageVersion>3.0.0-alpha1-10657</MicrosoftExtensionsProcessSourcesPackageVersion>
|
|
||||||
<MicrosoftNETCoreApp30PackageVersion>3.0.0-preview1-26907-05</MicrosoftNETCoreApp30PackageVersion>
|
|
||||||
<MicrosoftNETTestSdkPackageVersion>15.9.0</MicrosoftNETTestSdkPackageVersion>
|
|
||||||
<MicrosoftWebApiClientPackageVersion>5.2.6</MicrosoftWebApiClientPackageVersion>
|
|
||||||
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
|
|
||||||
<NewtonsoftJsonPackageVersion>11.0.2</NewtonsoftJsonPackageVersion>
|
|
||||||
<SystemDataSqlClientPackageVersion>4.6.0-preview1-26907-04</SystemDataSqlClientPackageVersion>
|
|
||||||
<SystemSecurityCryptographyCngPackageVersion>4.6.0-preview1-26907-04</SystemSecurityCryptographyCngPackageVersion>
|
|
||||||
<VisualStudio_NewtonsoftJsonPackageVersion>9.0.1</VisualStudio_NewtonsoftJsonPackageVersion>
|
|
||||||
<XunitPackageVersion>2.4.0</XunitPackageVersion>
|
|
||||||
<XunitRunnerVisualStudioPackageVersion>2.4.0</XunitRunnerVisualStudioPackageVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />
|
|
||||||
<PropertyGroup Label="Package Versions: Pinned" />
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
<Project>
|
|
||||||
<Import Project="dependencies.props" />
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp30PackageVersion)" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<!-- These properties are use by the automation that updates dependencies.props -->
|
|
||||||
<LineupPackageId>Internal.AspNetCore.Universe.Lineup</LineupPackageId>
|
|
||||||
<LineupPackageRestoreSource>https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json</LineupPackageRestoreSource>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
<Project>
|
|
||||||
<Import Project="VSIX.targets" />
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Solutions Update="$(RepositoryRoot)DotNetTools.sln">
|
|
||||||
<!-- the 'DebugNoVSIX' and 'ReleaseNoVSIX' configurations exclude the VSIX project, which doesn't build with Microsoft.NET.Sdk yet. -->
|
|
||||||
<AdditionalProperties>Configuration=$(Configuration)NoVSIX</AdditionalProperties>
|
|
||||||
</Solutions>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
<Project>
|
|
||||||
<Import Project="$(DotNetRestoreSourcePropsPath)" Condition="'$(DotNetRestoreSourcePropsPath)' != ''"/>
|
|
||||||
|
|
||||||
<PropertyGroup Label="RestoreSources">
|
|
||||||
<RestoreSources>$(DotNetRestoreSources)</RestoreSources>
|
|
||||||
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true' AND '$(AspNetUniverseBuildOffline)' != 'true' ">
|
|
||||||
$(RestoreSources);
|
|
||||||
https://dotnet.myget.org/F/dotnet-core/api/v3/index.json;
|
|
||||||
https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json;
|
|
||||||
https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
|
|
||||||
https://vside.myget.org/F/vssdk/api/v3/index.json;
|
|
||||||
https://vside.myget.org/F/devcore/api/v3/index.json
|
|
||||||
</RestoreSources>
|
|
||||||
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true'">
|
|
||||||
$(RestoreSources);
|
|
||||||
https://api.nuget.org/v3/index.json;
|
|
||||||
</RestoreSources>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,41 +1,41 @@
|
||||||
{
|
{
|
||||||
"adx": {
|
"adx": {
|
||||||
"rules": [
|
"rules": [
|
||||||
"AdxVerificationCompositeRule"
|
"AdxVerificationCompositeRule"
|
||||||
],
|
],
|
||||||
"packages": {
|
"packages": {
|
||||||
"dotnet-watch": {
|
"dotnet-watch": {
|
||||||
"packageTypes": [
|
"packageTypes": [
|
||||||
"DotnetTool"
|
"DotnetTool"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dotnet-sql-cache": {
|
"dotnet-sql-cache": {
|
||||||
"packageTypes": [
|
"packageTypes": [
|
||||||
"DotnetTool"
|
"DotnetTool"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dotnet-user-secrets": {
|
"dotnet-user-secrets": {
|
||||||
"packageTypes": [
|
"packageTypes": [
|
||||||
"DotnetTool"
|
"DotnetTool"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dotnet-dev-certs": {
|
"dotnet-dev-certs": {
|
||||||
"packageTypes": [
|
"packageTypes": [
|
||||||
"DotnetTool"
|
"DotnetTool"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Microsoft.AspNetCore.DeveloperCertificates.XPlat": {
|
"Microsoft.AspNetCore.DeveloperCertificates.XPlat": {
|
||||||
"Exclusions": {
|
"Exclusions": {
|
||||||
"DOC_MISSING": {
|
"DOC_MISSING": {
|
||||||
"lib/netcoreapp3.0/Microsoft.AspNetCore.DeveloperCertificates.XPlat.dll": "Docs not required to shipoob package"
|
"lib/netcoreapp3.0/Microsoft.AspNetCore.DeveloperCertificates.XPlat.dll": "Docs not required to shipoob package"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Default": {
|
"Default": {
|
||||||
"rules": [
|
"rules": [
|
||||||
"DefaultCompositeRule"
|
"DefaultCompositeRule"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
version:3.0.0-alpha1-20181026.5
|
|
||||||
commithash:0c0410ef8b17d5177a05b50cb66f9ad89ce15e32
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json",
|
|
||||||
"channel": "master",
|
|
||||||
"toolsets": {
|
|
||||||
"visualstudio": {
|
|
||||||
"required": [
|
|
||||||
"windows"
|
|
||||||
],
|
|
||||||
"includePrerelease": true,
|
|
||||||
"versionRange": "[15.0.26730.03, 16.0)",
|
|
||||||
"requiredWorkloads": [
|
|
||||||
"Microsoft.VisualStudio.Component.VSSDK"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2
run.cmd
2
run.cmd
|
|
@ -1,2 +0,0 @@
|
||||||
@ECHO OFF
|
|
||||||
PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE"
|
|
||||||
210
run.ps1
210
run.ps1
|
|
@ -1,210 +0,0 @@
|
||||||
#!/usr/bin/env powershell
|
|
||||||
#requires -version 4
|
|
||||||
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Executes KoreBuild commands.
|
|
||||||
|
|
||||||
.DESCRIPTION
|
|
||||||
Downloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`.
|
|
||||||
|
|
||||||
.PARAMETER Command
|
|
||||||
The KoreBuild command to run.
|
|
||||||
|
|
||||||
.PARAMETER Path
|
|
||||||
The folder to build. Defaults to the folder containing this script.
|
|
||||||
|
|
||||||
.PARAMETER Channel
|
|
||||||
The channel of KoreBuild to download. Overrides the value from the config file.
|
|
||||||
|
|
||||||
.PARAMETER DotNetHome
|
|
||||||
The directory where .NET Core tools will be stored.
|
|
||||||
|
|
||||||
.PARAMETER ToolsSource
|
|
||||||
The base url where build tools can be downloaded. Overrides the value from the config file.
|
|
||||||
|
|
||||||
.PARAMETER Update
|
|
||||||
Updates KoreBuild to the latest version even if a lock file is present.
|
|
||||||
|
|
||||||
.PARAMETER Reinstall
|
|
||||||
Re-installs KoreBuild
|
|
||||||
|
|
||||||
.PARAMETER ConfigFile
|
|
||||||
The path to the configuration file that stores values. Defaults to korebuild.json.
|
|
||||||
|
|
||||||
.PARAMETER ToolsSourceSuffix
|
|
||||||
The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores.
|
|
||||||
|
|
||||||
.PARAMETER CI
|
|
||||||
Sets up CI specific settings and variables.
|
|
||||||
|
|
||||||
.PARAMETER Arguments
|
|
||||||
Arguments to be passed to the command
|
|
||||||
|
|
||||||
.NOTES
|
|
||||||
This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be.
|
|
||||||
When the lockfile is not present, KoreBuild will create one using latest available version from $Channel.
|
|
||||||
|
|
||||||
The $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set
|
|
||||||
in the file are overridden by command line parameters.
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
Example config file:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json",
|
|
||||||
"channel": "master",
|
|
||||||
"toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
#>
|
|
||||||
[CmdletBinding(PositionalBinding = $false)]
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory = $true, Position = 0)]
|
|
||||||
[string]$Command,
|
|
||||||
[string]$Path = $PSScriptRoot,
|
|
||||||
[Alias('c')]
|
|
||||||
[string]$Channel,
|
|
||||||
[Alias('d')]
|
|
||||||
[string]$DotNetHome,
|
|
||||||
[Alias('s')]
|
|
||||||
[string]$ToolsSource,
|
|
||||||
[Alias('u')]
|
|
||||||
[switch]$Update,
|
|
||||||
[switch]$Reinstall,
|
|
||||||
[string]$ToolsSourceSuffix,
|
|
||||||
[string]$ConfigFile = $null,
|
|
||||||
[switch]$CI,
|
|
||||||
[Parameter(ValueFromRemainingArguments = $true)]
|
|
||||||
[string[]]$Arguments
|
|
||||||
)
|
|
||||||
|
|
||||||
Set-StrictMode -Version 2
|
|
||||||
$ErrorActionPreference = 'Stop'
|
|
||||||
|
|
||||||
#
|
|
||||||
# Functions
|
|
||||||
#
|
|
||||||
|
|
||||||
function Get-KoreBuild {
|
|
||||||
|
|
||||||
$lockFile = Join-Path $Path 'korebuild-lock.txt'
|
|
||||||
|
|
||||||
if (!(Test-Path $lockFile) -or $Update) {
|
|
||||||
Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile $ToolsSourceSuffix
|
|
||||||
}
|
|
||||||
|
|
||||||
$version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1
|
|
||||||
if (!$version) {
|
|
||||||
Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'"
|
|
||||||
}
|
|
||||||
$version = $version.TrimStart('version:').Trim()
|
|
||||||
$korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version)
|
|
||||||
|
|
||||||
if ($Reinstall -and (Test-Path $korebuildPath)) {
|
|
||||||
Remove-Item -Force -Recurse $korebuildPath
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(Test-Path $korebuildPath)) {
|
|
||||||
Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version"
|
|
||||||
New-Item -ItemType Directory -Path $korebuildPath | Out-Null
|
|
||||||
$remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip"
|
|
||||||
|
|
||||||
try {
|
|
||||||
$tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip"
|
|
||||||
Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix
|
|
||||||
if (Get-Command -Name 'Microsoft.PowerShell.Archive\Expand-Archive' -ErrorAction Ignore) {
|
|
||||||
# Use built-in commands where possible as they are cross-plat compatible
|
|
||||||
Microsoft.PowerShell.Archive\Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
# Fallback to old approach for old installations of PowerShell
|
|
||||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
|
||||||
[System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore
|
|
||||||
throw
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
Remove-Item $tmpfile -ErrorAction Ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $korebuildPath
|
|
||||||
}
|
|
||||||
|
|
||||||
function Join-Paths([string]$path, [string[]]$childPaths) {
|
|
||||||
$childPaths | ForEach-Object { $path = Join-Path $path $_ }
|
|
||||||
return $path
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get-RemoteFile([string]$RemotePath, [string]$LocalPath, [string]$RemoteSuffix) {
|
|
||||||
if ($RemotePath -notlike 'http*') {
|
|
||||||
Copy-Item $RemotePath $LocalPath
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
$retries = 10
|
|
||||||
while ($retries -gt 0) {
|
|
||||||
$retries -= 1
|
|
||||||
try {
|
|
||||||
Invoke-WebRequest -UseBasicParsing -Uri $($RemotePath + $RemoteSuffix) -OutFile $LocalPath
|
|
||||||
return
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Verbose "Request failed. $retries retries remaining"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Error "Download failed: '$RemotePath'."
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Main
|
|
||||||
#
|
|
||||||
|
|
||||||
# Load configuration or set defaults
|
|
||||||
|
|
||||||
$Path = Resolve-Path $Path
|
|
||||||
if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' }
|
|
||||||
|
|
||||||
if (Test-Path $ConfigFile) {
|
|
||||||
try {
|
|
||||||
$config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json
|
|
||||||
if ($config) {
|
|
||||||
if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel }
|
|
||||||
if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host -ForegroundColor Red $Error[0]
|
|
||||||
Write-Error "$ConfigFile contains invalid JSON."
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$DotNetHome) {
|
|
||||||
$DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } `
|
|
||||||
elseif ($CI) { Join-Path $PSScriptRoot '.dotnet' } `
|
|
||||||
elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} `
|
|
||||||
elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}`
|
|
||||||
else { Join-Path $PSScriptRoot '.dotnet'}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$Channel) { $Channel = 'master' }
|
|
||||||
if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' }
|
|
||||||
|
|
||||||
# Execute
|
|
||||||
|
|
||||||
$korebuildPath = Get-KoreBuild
|
|
||||||
Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1')
|
|
||||||
|
|
||||||
try {
|
|
||||||
Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile -CI:$CI
|
|
||||||
Invoke-KoreBuildCommand $Command @Arguments
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
Remove-Module 'KoreBuild' -ErrorAction Ignore
|
|
||||||
}
|
|
||||||
259
run.sh
259
run.sh
|
|
@ -1,259 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
#
|
|
||||||
# variables
|
|
||||||
#
|
|
||||||
|
|
||||||
RESET="\033[0m"
|
|
||||||
RED="\033[0;31m"
|
|
||||||
YELLOW="\033[0;33m"
|
|
||||||
MAGENTA="\033[0;95m"
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
verbose=false
|
|
||||||
update=false
|
|
||||||
reinstall=false
|
|
||||||
repo_path="$DIR"
|
|
||||||
channel=''
|
|
||||||
tools_source=''
|
|
||||||
tools_source_suffix=''
|
|
||||||
ci=false
|
|
||||||
|
|
||||||
#
|
|
||||||
# Functions
|
|
||||||
#
|
|
||||||
__usage() {
|
|
||||||
echo "Usage: $(basename "${BASH_SOURCE[0]}") command [options] [[--] <Arguments>...]"
|
|
||||||
echo ""
|
|
||||||
echo "Arguments:"
|
|
||||||
echo " command The command to be run."
|
|
||||||
echo " <Arguments>... Arguments passed to the command. Variable number of arguments allowed."
|
|
||||||
echo ""
|
|
||||||
echo "Options:"
|
|
||||||
echo " --verbose Show verbose output."
|
|
||||||
echo " -c|--channel <CHANNEL> The channel of KoreBuild to download. Overrides the value from the config file.."
|
|
||||||
echo " --config-file <FILE> The path to the configuration file that stores values. Defaults to korebuild.json."
|
|
||||||
echo " -d|--dotnet-home <DIR> The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet."
|
|
||||||
echo " --path <PATH> The directory to build. Defaults to the directory containing the script."
|
|
||||||
echo " -s|--tools-source|-ToolsSource <URL> The base url where build tools can be downloaded. Overrides the value from the config file."
|
|
||||||
echo " --tools-source-suffix|-ToolsSourceSuffix <SUFFIX> The suffix to append to tools-source. Useful for query strings."
|
|
||||||
echo " -u|--update Update to the latest KoreBuild even if the lock file is present."
|
|
||||||
echo " --reinstall Reinstall KoreBuild."
|
|
||||||
echo " --ci Apply CI specific settings and environment variables."
|
|
||||||
echo ""
|
|
||||||
echo "Description:"
|
|
||||||
echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be."
|
|
||||||
echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel."
|
|
||||||
|
|
||||||
if [[ "${1:-}" != '--no-exit' ]]; then
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
get_korebuild() {
|
|
||||||
local version
|
|
||||||
local lock_file="$repo_path/korebuild-lock.txt"
|
|
||||||
if [ ! -f "$lock_file" ] || [ "$update" = true ]; then
|
|
||||||
__get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" "$tools_source_suffix"
|
|
||||||
fi
|
|
||||||
version="$(grep 'version:*' -m 1 "$lock_file")"
|
|
||||||
if [[ "$version" == '' ]]; then
|
|
||||||
__error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
|
|
||||||
local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version"
|
|
||||||
|
|
||||||
if [ "$reinstall" = true ] && [ -d "$korebuild_path" ]; then
|
|
||||||
rm -rf "$korebuild_path"
|
|
||||||
fi
|
|
||||||
|
|
||||||
{
|
|
||||||
if [ ! -d "$korebuild_path" ]; then
|
|
||||||
mkdir -p "$korebuild_path"
|
|
||||||
local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip"
|
|
||||||
tmpfile="$(mktemp)"
|
|
||||||
echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}"
|
|
||||||
if __get_remote_file "$remote_path" "$tmpfile" "$tools_source_suffix"; then
|
|
||||||
unzip -q -d "$korebuild_path" "$tmpfile"
|
|
||||||
fi
|
|
||||||
rm "$tmpfile" || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
source "$korebuild_path/KoreBuild.sh"
|
|
||||||
} || {
|
|
||||||
if [ -d "$korebuild_path" ]; then
|
|
||||||
echo "Cleaning up after failed installation"
|
|
||||||
rm -rf "$korebuild_path" || true
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__error() {
|
|
||||||
echo -e "${RED}error: $*${RESET}" 1>&2
|
|
||||||
}
|
|
||||||
|
|
||||||
__warn() {
|
|
||||||
echo -e "${YELLOW}warning: $*${RESET}"
|
|
||||||
}
|
|
||||||
|
|
||||||
__machine_has() {
|
|
||||||
hash "$1" > /dev/null 2>&1
|
|
||||||
return $?
|
|
||||||
}
|
|
||||||
|
|
||||||
__get_remote_file() {
|
|
||||||
local remote_path=$1
|
|
||||||
local local_path=$2
|
|
||||||
local remote_path_suffix=$3
|
|
||||||
|
|
||||||
if [[ "$remote_path" != 'http'* ]]; then
|
|
||||||
cp "$remote_path" "$local_path"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
local failed=false
|
|
||||||
if __machine_has wget; then
|
|
||||||
wget --tries 10 --quiet -O "$local_path" "${remote_path}${remote_path_suffix}" || failed=true
|
|
||||||
else
|
|
||||||
failed=true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$failed" = true ] && __machine_has curl; then
|
|
||||||
failed=false
|
|
||||||
curl --retry 10 -sSL -f --create-dirs -o "$local_path" "${remote_path}${remote_path_suffix}" || failed=true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$failed" = true ]; then
|
|
||||||
__error "Download failed: $remote_path" 1>&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# main
|
|
||||||
#
|
|
||||||
|
|
||||||
command="${1:-}"
|
|
||||||
shift
|
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
|
||||||
case $1 in
|
|
||||||
-\?|-h|--help)
|
|
||||||
__usage --no-exit
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
-c|--channel|-Channel)
|
|
||||||
shift
|
|
||||||
channel="${1:-}"
|
|
||||||
[ -z "$channel" ] && __usage
|
|
||||||
;;
|
|
||||||
--config-file|-ConfigFile)
|
|
||||||
shift
|
|
||||||
config_file="${1:-}"
|
|
||||||
[ -z "$config_file" ] && __usage
|
|
||||||
if [ ! -f "$config_file" ]; then
|
|
||||||
__error "Invalid value for --config-file. $config_file does not exist."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
-d|--dotnet-home|-DotNetHome)
|
|
||||||
shift
|
|
||||||
DOTNET_HOME="${1:-}"
|
|
||||||
[ -z "$DOTNET_HOME" ] && __usage
|
|
||||||
;;
|
|
||||||
--path|-Path)
|
|
||||||
shift
|
|
||||||
repo_path="${1:-}"
|
|
||||||
[ -z "$repo_path" ] && __usage
|
|
||||||
;;
|
|
||||||
-s|--tools-source|-ToolsSource)
|
|
||||||
shift
|
|
||||||
tools_source="${1:-}"
|
|
||||||
[ -z "$tools_source" ] && __usage
|
|
||||||
;;
|
|
||||||
--tools-source-suffix|-ToolsSourceSuffix)
|
|
||||||
shift
|
|
||||||
tools_source_suffix="${1:-}"
|
|
||||||
[ -z "$tools_source_suffix" ] && __usage
|
|
||||||
;;
|
|
||||||
-u|--update|-Update)
|
|
||||||
update=true
|
|
||||||
;;
|
|
||||||
--reinstall|-[Rr]einstall)
|
|
||||||
reinstall=true
|
|
||||||
;;
|
|
||||||
--ci|-[Cc][Ii])
|
|
||||||
ci=true
|
|
||||||
if [[ -z "${DOTNET_HOME:-}" ]]; then
|
|
||||||
DOTNET_HOME="$DIR/.dotnet"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
--verbose|-Verbose)
|
|
||||||
verbose=true
|
|
||||||
;;
|
|
||||||
--)
|
|
||||||
shift
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
if ! __machine_has unzip; then
|
|
||||||
__error 'Missing required command: unzip'
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! __machine_has curl && ! __machine_has wget; then
|
|
||||||
__error 'Missing required command. Either wget or curl is required.'
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
[ -z "${config_file:-}" ] && config_file="$repo_path/korebuild.json"
|
|
||||||
if [ -f "$config_file" ]; then
|
|
||||||
if __machine_has jq ; then
|
|
||||||
if jq '.' "$config_file" >/dev/null ; then
|
|
||||||
config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")"
|
|
||||||
config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")"
|
|
||||||
else
|
|
||||||
__error "$config_file contains invalid JSON."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
elif __machine_has python ; then
|
|
||||||
if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then
|
|
||||||
config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")"
|
|
||||||
config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")"
|
|
||||||
else
|
|
||||||
__error "$config_file contains invalid JSON."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
elif __machine_has python3 ; then
|
|
||||||
if python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then
|
|
||||||
config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")"
|
|
||||||
config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")"
|
|
||||||
else
|
|
||||||
__error "$config_file contains invalid JSON."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
__error 'Missing required command: jq or python. Could not parse the JSON file.'
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
[ ! -z "${config_channel:-}" ] && channel="$config_channel"
|
|
||||||
[ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source"
|
|
||||||
fi
|
|
||||||
|
|
||||||
[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet"
|
|
||||||
[ -z "$channel" ] && channel='master'
|
|
||||||
[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools'
|
|
||||||
|
|
||||||
get_korebuild
|
|
||||||
set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" "$ci"
|
|
||||||
invoke_korebuild_command "$command" "$@"
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
<!-- Intentionally empty to isolate the samples. -->
|
|
||||||
<Project />
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
<!-- Intentionally empty to isolate the samples. -->
|
|
||||||
<Project />
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Watch Include="say-hello.js" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="RunMyNpmCommand">
|
|
||||||
<Exec Command="npm run custom" />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
Launch any command with dotnet-watch
|
|
||||||
====================================
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
1. Install .NET Core command line. <https://dot.net/core>
|
|
||||||
2. Install NodeJS. <https://nodejs.org>
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Open a terminal to the directory containing this project.
|
|
||||||
|
|
||||||
```
|
|
||||||
dotnet watch msbuild /t:RunMyNpmCommand
|
|
||||||
```
|
|
||||||
|
|
||||||
Changing the .csproj file, or the say-hello.js file will cause dotnet-watch to re-run the 'RunMyNpmCommand' target in MyApp.csproj.
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"name": "any-command",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"custom": "node say-hello.js"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
console.log("Hello from Javascript");
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
dotnet-watch samples
|
|
||||||
====================
|
|
||||||
|
|
||||||
The samples in this folder show some ways to customize dotnet-watch. For full details on
|
|
||||||
available settings and configuration, see the [README for the dotnet-watch](../../src/dotnet-watch/README.md) project.
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.IO;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
|
|
||||||
namespace WatchJavascriptFiles
|
|
||||||
{
|
|
||||||
public class Program
|
|
||||||
{
|
|
||||||
public static void Main(string[] args)
|
|
||||||
{
|
|
||||||
var host = new WebHostBuilder()
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.Configure(app =>
|
|
||||||
app.Run(async (context) =>
|
|
||||||
{
|
|
||||||
await context.Response.WriteAsync("Hello World!");
|
|
||||||
}))
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
host.Run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
Watch JavaScript files with dotnet-watch
|
|
||||||
========================================
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
Install .NET Core command line. <https://dot.net/core>
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Open a terminal to the directory containing this project.
|
|
||||||
|
|
||||||
```
|
|
||||||
dotnet watch run
|
|
||||||
```
|
|
||||||
|
|
||||||
Changing the .csproj file, or \*.js file in wwwroot, or any \*.cs file will cause dotnet-watch to restart the website.
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="wwwroot\" />
|
|
||||||
<Watch Include="wwwroot\**\*.js" Exclude="wwwroot\node_modules\**\*.js" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
document.title = "My awesome website";
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
Watch multiple projects with dotnet-watch
|
|
||||||
=========================================
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
Install .NET Core command line. <https://dot.net/core>
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Open a terminal to the directory containing this project.
|
|
||||||
|
|
||||||
```
|
|
||||||
dotnet watch msbuild /t:TestAndRun
|
|
||||||
```
|
|
||||||
|
|
||||||
The "TestAndRun" target in watch.proj will execute "dotnet test" on Test.csproj and then launch the website by calling "dotnet run" on Web.csproj.
|
|
||||||
|
|
||||||
Changing any \*.cs file in Test/ or Web/, any \*.csproj file, or watch.proj, will cause dotnet-watch to relaunch the "TestAndRun" target from watch.proj.
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
|
|
||||||
<PackageReference Include="xunit" Version="2.2.0" />
|
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Test
|
|
||||||
{
|
|
||||||
public class UnitTest1
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public void Test1()
|
|
||||||
{
|
|
||||||
Assert.True(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.IO;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
|
|
||||||
namespace Web
|
|
||||||
{
|
|
||||||
public class Program
|
|
||||||
{
|
|
||||||
public static void Main(string[] args)
|
|
||||||
{
|
|
||||||
var host = new WebHostBuilder()
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.Configure(app =>
|
|
||||||
app.Run(async (context) =>
|
|
||||||
{
|
|
||||||
await context.Response.WriteAsync("Hello World!");
|
|
||||||
}))
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
host.Run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="wwwroot\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
|
||||||
<EnableDefaultItems>false</EnableDefaultItems>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="Web\Web.csproj" />
|
|
||||||
<ProjectReference Include="Test\Test.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="TestAndRun">
|
|
||||||
<Exec Command="dotnet test" WorkingDirectory="Test/" />
|
|
||||||
<Exec Command="dotnet run" WorkingDirectory="Web/" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
<Project>
|
|
||||||
<Import Project="..\Directory.Build.props" />
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Internal.AspNetCore.Sdk" PrivateAssets="All" Version="$(InternalAspNetCoreSdkPackageVersion)" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
<Project>
|
|
||||||
<Import Project="..\Directory.Build.targets" />
|
|
||||||
|
|
||||||
<Target Name="CleanPublishDir" AfterTargets="CoreClean">
|
|
||||||
<RemoveDir Directories="$(PublishDir)" />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl
|
|
||||||
{
|
|
||||||
public class AggregateDirectoryStructure : IDirectoryStructure
|
|
||||||
{
|
|
||||||
private readonly IDirectoryStructure _first;
|
|
||||||
private readonly IDirectoryStructure _second;
|
|
||||||
|
|
||||||
public AggregateDirectoryStructure(IDirectoryStructure first, IDirectoryStructure second)
|
|
||||||
{
|
|
||||||
_first = first;
|
|
||||||
_second = second;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> DirectoryNames
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
HashSet<string> values = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
values.UnionWith(_first.DirectoryNames);
|
|
||||||
values.UnionWith(_second.DirectoryNames);
|
|
||||||
return values.OrderBy(x => x, StringComparer.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDirectoryStructure Parent => _first.Parent ?? _second.Parent;
|
|
||||||
|
|
||||||
public IDirectoryStructure GetChildDirectory(string name)
|
|
||||||
{
|
|
||||||
return new AggregateDirectoryStructure(_first.GetChildDirectory(name), _second.GetChildDirectory(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public IRequestInfo RequestInfo => _first.RequestInfo ?? _second.RequestInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,611 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
using Microsoft.HttpRepl.Formatting;
|
|
||||||
using Microsoft.HttpRepl.Preferences;
|
|
||||||
using Microsoft.HttpRepl.Suggestions;
|
|
||||||
using Microsoft.Repl;
|
|
||||||
using Microsoft.Repl.Commanding;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
using Microsoft.Repl.Parsing;
|
|
||||||
using Microsoft.Repl.Suggestions;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public abstract class BaseHttpCommand : CommandWithStructuredInputBase<HttpState, ICoreParseResult>
|
|
||||||
{
|
|
||||||
private const string HeaderOption = nameof(HeaderOption);
|
|
||||||
private const string ResponseHeadersFileOption = nameof(ResponseHeadersFileOption);
|
|
||||||
private const string ResponseBodyFileOption = nameof(ResponseBodyFileOption);
|
|
||||||
private const string ResponseFileOption = nameof(ResponseFileOption);
|
|
||||||
private const string BodyFileOption = nameof(BodyFileOption);
|
|
||||||
private const string NoBodyOption = nameof(NoBodyOption);
|
|
||||||
private const string NoFormattingOption = nameof(NoFormattingOption);
|
|
||||||
private const string StreamingOption = nameof(StreamingOption);
|
|
||||||
private const string BodyContentOption = nameof(BodyContentOption);
|
|
||||||
private static readonly char[] HeaderSeparatorChars = new[] { '=', ':' };
|
|
||||||
|
|
||||||
private CommandInputSpecification _inputSpec;
|
|
||||||
|
|
||||||
protected abstract string Verb { get; }
|
|
||||||
|
|
||||||
protected abstract bool RequiresBody { get; }
|
|
||||||
|
|
||||||
public override CommandInputSpecification InputSpec
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_inputSpec != null)
|
|
||||||
{
|
|
||||||
return _inputSpec;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandInputSpecificationBuilder builder = CommandInputSpecification.Create(Verb)
|
|
||||||
.MaximumArgCount(1)
|
|
||||||
.WithOption(new CommandOptionSpecification(HeaderOption, requiresValue: true, forms: new[] {"--header", "-h"}))
|
|
||||||
.WithOption(new CommandOptionSpecification(ResponseFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response", }))
|
|
||||||
.WithOption(new CommandOptionSpecification(ResponseHeadersFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response:headers", }))
|
|
||||||
.WithOption(new CommandOptionSpecification(ResponseBodyFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response:body", }))
|
|
||||||
.WithOption(new CommandOptionSpecification(NoFormattingOption, maximumOccurrences: 1, forms: new[] { "--no-formatting", "-F" }))
|
|
||||||
.WithOption(new CommandOptionSpecification(StreamingOption, maximumOccurrences: 1, forms: new[] { "--streaming", "-s" }));
|
|
||||||
|
|
||||||
if (RequiresBody)
|
|
||||||
{
|
|
||||||
builder = builder.WithOption(new CommandOptionSpecification(NoBodyOption, maximumOccurrences: 1, forms: "--no-body"))
|
|
||||||
.WithOption(new CommandOptionSpecification(BodyFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] {"--file", "-f"}))
|
|
||||||
.WithOption(new CommandOptionSpecification(BodyContentOption, requiresValue: true, maximumOccurrences: 1, forms: new[] {"--content", "-c"}));
|
|
||||||
}
|
|
||||||
|
|
||||||
_inputSpec = builder.Finish();
|
|
||||||
return _inputSpec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (programState.BaseAddress == null && (commandInput.Arguments.Count == 0 || !Uri.TryCreate(commandInput.Arguments[0].Text, UriKind.Absolute, out Uri _)))
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("'set base {url}' must be called before issuing requests to a relative path".SetColor(programState.ErrorColor));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (programState.SwaggerEndpoint != null)
|
|
||||||
{
|
|
||||||
string swaggerRequeryBehaviorSetting = programState.GetStringPreference(WellKnownPreference.SwaggerRequeryBehavior, "auto");
|
|
||||||
|
|
||||||
if (swaggerRequeryBehaviorSetting.StartsWith("auto", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, programState, programState.SwaggerEndpoint, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary<string, string> thisRequestHeaders = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
foreach (InputElement header in commandInput.Options[HeaderOption])
|
|
||||||
{
|
|
||||||
int equalsIndex = header.Text.IndexOfAny(HeaderSeparatorChars);
|
|
||||||
|
|
||||||
if (equalsIndex < 0)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("Headers must be formatted as {header}={value} or {header}:{value}".SetColor(programState.ErrorColor));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
thisRequestHeaders[header.Text.Substring(0, equalsIndex)] = header.Text.Substring(equalsIndex + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Uri effectivePath = programState.GetEffectivePath(commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty);
|
|
||||||
HttpRequestMessage request = new HttpRequestMessage(new HttpMethod(Verb.ToUpperInvariant()), effectivePath);
|
|
||||||
bool noBody = false;
|
|
||||||
|
|
||||||
if (RequiresBody)
|
|
||||||
{
|
|
||||||
string filePath = null;
|
|
||||||
string bodyContent = null;
|
|
||||||
bool deleteFile = false;
|
|
||||||
noBody = commandInput.Options[NoBodyOption].Count > 0;
|
|
||||||
|
|
||||||
if (!thisRequestHeaders.TryGetValue("content-type", out string contentType) && programState.Headers.TryGetValue("content-type", out IEnumerable<string> contentTypes))
|
|
||||||
{
|
|
||||||
contentType = contentTypes.FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!noBody)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(contentType))
|
|
||||||
{
|
|
||||||
contentType = "application/json";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commandInput.Options[BodyFileOption].Count > 0)
|
|
||||||
{
|
|
||||||
filePath = commandInput.Options[BodyFileOption][0].Text;
|
|
||||||
|
|
||||||
if (!File.Exists(filePath))
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine($"Content file {filePath} does not exist".SetColor(programState.ErrorColor));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (commandInput.Options[BodyContentOption].Count > 0)
|
|
||||||
{
|
|
||||||
bodyContent = commandInput.Options[BodyContentOption][0].Text;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string defaultEditorCommand = programState.GetStringPreference(WellKnownPreference.DefaultEditorCommand);
|
|
||||||
if (defaultEditorCommand == null)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine($"The default editor must be configured using the command `pref set {WellKnownPreference.DefaultEditorCommand} \"{{commandline}}\"`".SetColor(programState.ErrorColor));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteFile = true;
|
|
||||||
filePath = Path.GetTempFileName();
|
|
||||||
|
|
||||||
string exampleBody = programState.GetExampleBody(commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty, ref contentType, Verb);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(exampleBody))
|
|
||||||
{
|
|
||||||
File.WriteAllText(filePath, exampleBody);
|
|
||||||
}
|
|
||||||
|
|
||||||
string defaultEditorArguments = programState.GetStringPreference(WellKnownPreference.DefaultEditorArguments) ?? "";
|
|
||||||
string original = defaultEditorArguments;
|
|
||||||
string pathString = $"\"{filePath}\"";
|
|
||||||
|
|
||||||
defaultEditorArguments = defaultEditorArguments.Replace("{filename}", pathString);
|
|
||||||
|
|
||||||
if (string.Equals(defaultEditorArguments, original, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
defaultEditorArguments = (defaultEditorArguments + " " + pathString).Trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessStartInfo info = new ProcessStartInfo(defaultEditorCommand, defaultEditorArguments);
|
|
||||||
|
|
||||||
Process.Start(info)?.WaitForExit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(contentType))
|
|
||||||
{
|
|
||||||
contentType = "application/json";
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] data = noBody
|
|
||||||
? new byte[0]
|
|
||||||
: string.IsNullOrEmpty(bodyContent)
|
|
||||||
? File.ReadAllBytes(filePath)
|
|
||||||
: Encoding.UTF8.GetBytes(bodyContent);
|
|
||||||
|
|
||||||
HttpContent content = new ByteArrayContent(data);
|
|
||||||
content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
|
|
||||||
request.Content = content;
|
|
||||||
|
|
||||||
if (deleteFile)
|
|
||||||
{
|
|
||||||
File.Delete(filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, IEnumerable<string>> header in programState.Headers)
|
|
||||||
{
|
|
||||||
content.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, string> header in thisRequestHeaders)
|
|
||||||
{
|
|
||||||
content.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, IEnumerable<string>> header in programState.Headers)
|
|
||||||
{
|
|
||||||
request.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, string> header in thisRequestHeaders)
|
|
||||||
{
|
|
||||||
request.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
string headersTarget = commandInput.Options[ResponseHeadersFileOption].FirstOrDefault()?.Text ?? commandInput.Options[ResponseFileOption].FirstOrDefault()?.Text;
|
|
||||||
string bodyTarget = commandInput.Options[ResponseBodyFileOption].FirstOrDefault()?.Text ?? commandInput.Options[ResponseFileOption].FirstOrDefault()?.Text;
|
|
||||||
|
|
||||||
HttpResponseMessage response = await programState.Client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
|
|
||||||
await HandleResponseAsync(programState, commandInput, shellState.ConsoleManager, response, programState.EchoRequest, headersTarget, bodyTarget, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task HandleResponseAsync(HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, IConsoleManager consoleManager, HttpResponseMessage response, bool echoRequest, string headersTargetFile, string bodyTargetFile, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
RequestConfig requestConfig = new RequestConfig(programState);
|
|
||||||
ResponseConfig responseConfig = new ResponseConfig(programState);
|
|
||||||
string protocolInfo;
|
|
||||||
|
|
||||||
if (echoRequest)
|
|
||||||
{
|
|
||||||
string hostString = response.RequestMessage.RequestUri.Scheme + "://" + response.RequestMessage.RequestUri.Host + (!response.RequestMessage.RequestUri.IsDefaultPort ? ":" + response.RequestMessage.RequestUri.Port : "");
|
|
||||||
consoleManager.WriteLine($"Request to {hostString}...".SetColor(requestConfig.AddressColor));
|
|
||||||
consoleManager.WriteLine();
|
|
||||||
|
|
||||||
string method = response.RequestMessage.Method.ToString().ToUpperInvariant().SetColor(requestConfig.MethodColor);
|
|
||||||
string pathAndQuery = response.RequestMessage.RequestUri.PathAndQuery.SetColor(requestConfig.AddressColor);
|
|
||||||
protocolInfo = $"{"HTTP".SetColor(requestConfig.ProtocolNameColor)}{"/".SetColor(requestConfig.ProtocolSeparatorColor)}{response.Version.ToString().SetColor(requestConfig.ProtocolVersionColor)}";
|
|
||||||
|
|
||||||
consoleManager.WriteLine($"{method} {pathAndQuery} {protocolInfo}");
|
|
||||||
IEnumerable<KeyValuePair<string, IEnumerable<string>>> requestHeaders = response.RequestMessage.Headers;
|
|
||||||
|
|
||||||
if (response.RequestMessage.Content != null)
|
|
||||||
{
|
|
||||||
requestHeaders = requestHeaders.Union(response.RequestMessage.Content.Headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, IEnumerable<string>> header in requestHeaders.OrderBy(x => x.Key))
|
|
||||||
{
|
|
||||||
string headerKey = header.Key.SetColor(requestConfig.HeaderKeyColor);
|
|
||||||
string headerSep = ":".SetColor(requestConfig.HeaderSeparatorColor);
|
|
||||||
string headerValue = string.Join(";".SetColor(requestConfig.HeaderValueSeparatorColor), header.Value.Select(x => x.Trim().SetColor(requestConfig.HeaderValueColor)));
|
|
||||||
consoleManager.WriteLine($"{headerKey}{headerSep} {headerValue}");
|
|
||||||
}
|
|
||||||
|
|
||||||
consoleManager.WriteLine();
|
|
||||||
|
|
||||||
if (response.RequestMessage.Content != null)
|
|
||||||
{
|
|
||||||
using (StreamWriter writer = new StreamWriter(new MemoryStream()))
|
|
||||||
{
|
|
||||||
await FormatBodyAsync(commandInput, programState, consoleManager, response.RequestMessage.Content, writer, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
consoleManager.WriteLine();
|
|
||||||
consoleManager.WriteLine($"Response from {hostString}...".SetColor(requestConfig.AddressColor));
|
|
||||||
consoleManager.WriteLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
protocolInfo = $"{"HTTP".SetColor(responseConfig.ProtocolNameColor)}{"/".SetColor(responseConfig.ProtocolSeparatorColor)}{response.Version.ToString().SetColor(responseConfig.ProtocolVersionColor)}";
|
|
||||||
string status = ((int)response.StatusCode).ToString().SetColor(responseConfig.StatusCodeColor) + " " + response.ReasonPhrase.SetColor(responseConfig.StatusReasonPhraseColor);
|
|
||||||
|
|
||||||
consoleManager.WriteLine($"{protocolInfo} {status}");
|
|
||||||
|
|
||||||
IEnumerable<KeyValuePair<string, IEnumerable<string>>> responseHeaders = response.Headers;
|
|
||||||
|
|
||||||
if (response.Content != null)
|
|
||||||
{
|
|
||||||
responseHeaders = responseHeaders.Union(response.Content.Headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamWriter headerFileWriter;
|
|
||||||
|
|
||||||
if (headersTargetFile != null)
|
|
||||||
{
|
|
||||||
headerFileWriter = new StreamWriter(File.Create(headersTargetFile));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
headerFileWriter = new StreamWriter(new MemoryStream());
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, IEnumerable<string>> header in responseHeaders.OrderBy(x => x.Key))
|
|
||||||
{
|
|
||||||
string headerKey = header.Key.SetColor(responseConfig.HeaderKeyColor);
|
|
||||||
string headerSep = ":".SetColor(responseConfig.HeaderSeparatorColor);
|
|
||||||
string headerValue = string.Join(";".SetColor(responseConfig.HeaderValueSeparatorColor), header.Value.Select(x => x.Trim().SetColor(responseConfig.HeaderValueColor)));
|
|
||||||
consoleManager.WriteLine($"{headerKey}{headerSep} {headerValue}");
|
|
||||||
headerFileWriter.WriteLine($"{header.Key}: {string.Join(";", header.Value.Select(x => x.Trim()))}");
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamWriter bodyFileWriter;
|
|
||||||
if (!string.Equals(headersTargetFile, bodyTargetFile, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
headerFileWriter.Flush();
|
|
||||||
headerFileWriter.Close();
|
|
||||||
headerFileWriter.Dispose();
|
|
||||||
|
|
||||||
if (bodyTargetFile != null)
|
|
||||||
{
|
|
||||||
bodyFileWriter = new StreamWriter(File.Create(bodyTargetFile));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bodyFileWriter = new StreamWriter(new MemoryStream());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
headerFileWriter.WriteLine();
|
|
||||||
bodyFileWriter = headerFileWriter;
|
|
||||||
}
|
|
||||||
|
|
||||||
consoleManager.WriteLine();
|
|
||||||
|
|
||||||
if (response.Content != null)
|
|
||||||
{
|
|
||||||
await FormatBodyAsync(commandInput, programState, consoleManager, response.Content, bodyFileWriter, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bodyFileWriter.Flush();
|
|
||||||
bodyFileWriter.Close();
|
|
||||||
bodyFileWriter.Dispose();
|
|
||||||
|
|
||||||
consoleManager.WriteLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task FormatBodyAsync(DefaultCommandInput<ICoreParseResult> commandInput, HttpState programState, IConsoleManager consoleManager, HttpContent content, StreamWriter bodyFileWriter, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (commandInput.Options[StreamingOption].Count > 0)
|
|
||||||
{
|
|
||||||
Memory<char> buffer = new Memory<char>(new char[2048]);
|
|
||||||
Stream s = await content.ReadAsStreamAsync().ConfigureAwait(false);
|
|
||||||
StreamReader reader = new StreamReader(s);
|
|
||||||
consoleManager.WriteLine("Streaming the response, press any key to stop...".SetColor(programState.WarningColor));
|
|
||||||
|
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ValueTask<int> readTask = reader.ReadAsync(buffer, cancellationToken);
|
|
||||||
if (await WaitForCompletionAsync(readTask, cancellationToken).ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
if (readTask.Result == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
string str = new string(buffer.Span.Slice(0, readTask.Result));
|
|
||||||
consoleManager.Write(str);
|
|
||||||
bodyFileWriter.Write(str);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string contentType = null;
|
|
||||||
if (content.Headers.TryGetValues("Content-Type", out IEnumerable<string> contentTypeValues))
|
|
||||||
{
|
|
||||||
contentType = contentTypeValues.FirstOrDefault()?.Split(';').FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
contentType = contentType?.ToUpperInvariant() ?? "text/plain";
|
|
||||||
|
|
||||||
if (commandInput.Options[NoFormattingOption].Count == 0)
|
|
||||||
{
|
|
||||||
if (contentType.EndsWith("/JSON", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| contentType.EndsWith("-JSON", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| contentType.EndsWith("+JSON", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| contentType.EndsWith("/JAVASCRIPT", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| contentType.EndsWith("-JAVASCRIPT", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| contentType.EndsWith("+JAVASCRIPT", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
if (await FormatJsonAsync(programState, consoleManager, content, bodyFileWriter))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (contentType.EndsWith("/HTML", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| contentType.EndsWith("-HTML", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| contentType.EndsWith("+HTML", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| contentType.EndsWith("/XML", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| contentType.EndsWith("-XML", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| contentType.EndsWith("+XML", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
if (await FormatXmlAsync(consoleManager, content, bodyFileWriter))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string responseContent = await content.ReadAsStringAsync().ConfigureAwait(false);
|
|
||||||
bodyFileWriter.WriteLine(responseContent);
|
|
||||||
consoleManager.WriteLine(responseContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<bool> WaitForCompletionAsync(ValueTask<int> readTask, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
while (!readTask.IsCompleted && !cancellationToken.IsCancellationRequested && !Console.KeyAvailable)
|
|
||||||
{
|
|
||||||
await Task.Delay(1, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Console.KeyAvailable)
|
|
||||||
{
|
|
||||||
Console.ReadKey(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return readTask.IsCompleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<bool> FormatXmlAsync(IWritable consoleManager, HttpContent content, StreamWriter bodyFileWriter)
|
|
||||||
{
|
|
||||||
string responseContent = await content.ReadAsStringAsync().ConfigureAwait(false);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
XDocument body = XDocument.Parse(responseContent);
|
|
||||||
consoleManager.WriteLine(body.ToString());
|
|
||||||
bodyFileWriter.WriteLine(body.ToString());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<bool> FormatJsonAsync(HttpState programState, IWritable outputSink, HttpContent content, StreamWriter bodyFileWriter)
|
|
||||||
{
|
|
||||||
string responseContent = await content.ReadAsStringAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
JsonConfig config = new JsonConfig(programState);
|
|
||||||
string formatted = JsonVisitor.FormatAndColorize(config, responseContent);
|
|
||||||
outputSink.WriteLine(formatted);
|
|
||||||
bodyFileWriter.WriteLine(JToken.Parse(responseContent).ToString());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
var helpText = new StringBuilder();
|
|
||||||
helpText.Append("Usage: ".Bold());
|
|
||||||
helpText.AppendLine($"{Verb.ToUpperInvariant()} [Options]");
|
|
||||||
helpText.AppendLine();
|
|
||||||
helpText.AppendLine($"Issues a {Verb.ToUpperInvariant()} request.");
|
|
||||||
|
|
||||||
if (RequiresBody)
|
|
||||||
{
|
|
||||||
helpText.AppendLine("Your default editor will be opened with a sample body if no options are provided.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return helpText.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetHelpSummary(IShellState shellState, HttpState programState)
|
|
||||||
{
|
|
||||||
return $"{Verb.ToLowerInvariant()} - Issues a {Verb.ToUpperInvariant()} request";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override IEnumerable<string> GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput<ICoreParseResult> commandInput, string normalCompletionString)
|
|
||||||
{
|
|
||||||
List<string> results = new List<string>();
|
|
||||||
|
|
||||||
if (programState.Structure != null && programState.BaseAddress != null)
|
|
||||||
{
|
|
||||||
//If it's an absolute URI, nothing to suggest
|
|
||||||
if (Uri.TryCreate(parseResult.Sections[1], UriKind.Absolute, out Uri _))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
string path = normalCompletionString.Replace('\\', '/');
|
|
||||||
int searchFrom = normalCompletionString.Length - 1;
|
|
||||||
int lastSlash = path.LastIndexOf('/', searchFrom);
|
|
||||||
string prefix;
|
|
||||||
|
|
||||||
if (lastSlash < 0)
|
|
||||||
{
|
|
||||||
path = string.Empty;
|
|
||||||
prefix = normalCompletionString;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
path = path.Substring(0, lastSlash + 1);
|
|
||||||
prefix = normalCompletionString.Substring(lastSlash + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse()).TraverseTo(path);
|
|
||||||
|
|
||||||
foreach (string child in s.DirectoryNames)
|
|
||||||
{
|
|
||||||
if (child.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
results.Add(path + child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override IEnumerable<string> GetOptionValueCompletions(IShellState shellState, HttpState programState, string optionId, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, string normalizedCompletionText)
|
|
||||||
{
|
|
||||||
if (string.Equals(optionId, BodyFileOption, StringComparison.Ordinal) || string.Equals(optionId, ResponseFileOption, StringComparison.OrdinalIgnoreCase) || string.Equals(optionId, ResponseBodyFileOption, StringComparison.OrdinalIgnoreCase) || string.Equals(optionId, ResponseHeadersFileOption, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return FileSystemCompletion.GetCompletions(normalizedCompletionText);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(optionId, HeaderOption, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
HashSet<string> alreadySpecifiedHeaders = new HashSet<string>(StringComparer.Ordinal);
|
|
||||||
IReadOnlyList<InputElement> options = commandInput.Options[HeaderOption];
|
|
||||||
for (int i = 0; i < options.Count; ++i)
|
|
||||||
{
|
|
||||||
if (options[i] == commandInput.SelectedElement)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
string elementText = options[i].Text;
|
|
||||||
string existingHeaderName = elementText.Split(HeaderSeparatorChars)[0];
|
|
||||||
alreadySpecifiedHeaders.Add(existingHeaderName);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check to see if the selected element is in a header name or value
|
|
||||||
int equalsIndex = normalizedCompletionText.IndexOfAny(HeaderSeparatorChars);
|
|
||||||
string path = commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty;
|
|
||||||
|
|
||||||
if (equalsIndex < 0)
|
|
||||||
{
|
|
||||||
IEnumerable<string> headerNameOptions = HeaderCompletion.GetCompletions(alreadySpecifiedHeaders, normalizedCompletionText);
|
|
||||||
|
|
||||||
if (headerNameOptions == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<string> allSuggestions = new List<string>();
|
|
||||||
foreach (string suggestion in headerNameOptions.Select(x => x))
|
|
||||||
{
|
|
||||||
allSuggestions.Add(suggestion + ":");
|
|
||||||
|
|
||||||
IEnumerable<string> suggestions = HeaderCompletion.GetValueCompletions(Verb, path, suggestion, string.Empty, programState);
|
|
||||||
|
|
||||||
if (suggestions != null)
|
|
||||||
{
|
|
||||||
foreach (string valueSuggestion in suggestions)
|
|
||||||
{
|
|
||||||
allSuggestions.Add(suggestion + ":" + valueSuggestion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return allSuggestions;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Didn't exit from the header name check, so must be a value
|
|
||||||
string headerName = normalizedCompletionText.Substring(0, equalsIndex);
|
|
||||||
IEnumerable<string> suggestions = HeaderCompletion.GetValueCompletions(Verb, path, headerName, normalizedCompletionText.Substring(equalsIndex + 1), programState);
|
|
||||||
|
|
||||||
if (suggestions == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return suggestions.Select(x => normalizedCompletionText.Substring(0, equalsIndex + 1) + x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.HttpRepl.Suggestions;
|
|
||||||
using Microsoft.Repl;
|
|
||||||
using Microsoft.Repl.Commanding;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
using Microsoft.Repl.Parsing;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class ChangeDirectoryCommand : CommandWithStructuredInputBase<HttpState, ICoreParseResult>
|
|
||||||
{
|
|
||||||
protected override Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (commandInput.Arguments.Count == 0 || string.IsNullOrEmpty(commandInput.Arguments[0]?.Text))
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.WriteLine($"/{string.Join("/", programState.PathSections.Reverse())}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string[] parts = commandInput.Arguments[0].Text.Replace('\\', '/').Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
|
|
||||||
if (commandInput.Arguments[0].Text.StartsWith("/", StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
programState.PathSections.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (string part in parts)
|
|
||||||
{
|
|
||||||
switch (part)
|
|
||||||
{
|
|
||||||
case ".":
|
|
||||||
break;
|
|
||||||
case "..":
|
|
||||||
if (programState.PathSections.Count > 0)
|
|
||||||
{
|
|
||||||
programState.PathSections.Pop();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
programState.PathSections.Push(part);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse());
|
|
||||||
|
|
||||||
string thisDirMethod = s.RequestInfo != null && s.RequestInfo.Methods.Count > 0
|
|
||||||
? "[" + string.Join("|", s.RequestInfo.Methods) + "]"
|
|
||||||
: "[]";
|
|
||||||
|
|
||||||
shellState.ConsoleManager.WriteLine($"/{string.Join("/", programState.PathSections.Reverse())} {thisDirMethod}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("cd")
|
|
||||||
.MaximumArgCount(1)
|
|
||||||
.Finish();
|
|
||||||
|
|
||||||
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
var help = new StringBuilder();
|
|
||||||
help.Append("Usage:".Bold());
|
|
||||||
help.AppendLine("cd [directory]");
|
|
||||||
help.AppendLine();
|
|
||||||
help.AppendLine("Prints the current directory if no argument is specified, otherwise changes to the specified directory");
|
|
||||||
|
|
||||||
return help.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetHelpSummary(IShellState shellState, HttpState programState)
|
|
||||||
{
|
|
||||||
return "cd [directory name] - Prints the current directory if no argument is specified, otherwise changes to the specified directory";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override IEnumerable<string> GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput<ICoreParseResult> commandInput, string normalCompletionString)
|
|
||||||
{
|
|
||||||
return ServerPathCompletion.GetCompletions(programState, normalCompletionString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Repl;
|
|
||||||
using Microsoft.Repl.Commanding;
|
|
||||||
using Microsoft.Repl.Parsing;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class ClearCommand : ICommand<object, ICoreParseResult>
|
|
||||||
{
|
|
||||||
private static readonly string Name = "clear";
|
|
||||||
private static readonly string AlternateName = "cls";
|
|
||||||
|
|
||||||
public bool? CanHandle(IShellState shellState, object programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
return parseResult.Sections.Count == 1 && (string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) || string.Equals(parseResult.Sections[0], AlternateName, StringComparison.OrdinalIgnoreCase))
|
|
||||||
? (bool?) true
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task ExecuteAsync(IShellState shellState, object programState, ICoreParseResult parseResult, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Clear();
|
|
||||||
shellState.CommandDispatcher.OnReady(shellState);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpDetails(IShellState shellState, object programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count == 1 && (string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) || string.Equals(parseResult.Sections[0], AlternateName, StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
return "Clears the shell";
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpSummary(IShellState shellState, object programState)
|
|
||||||
{
|
|
||||||
return "clear - Clears the shell";
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> Suggest(IShellState shellState, object programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
if (parseResult.SelectedSection == 0 &&
|
|
||||||
(string.IsNullOrEmpty(parseResult.Sections[parseResult.SelectedSection]) || Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
return new[] { Name };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseResult.SelectedSection == 0 &&
|
|
||||||
(string.IsNullOrEmpty(parseResult.Sections[parseResult.SelectedSection]) || AlternateName.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
return new[] { Name };
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.HttpRepl.Diagnostics;
|
|
||||||
using Microsoft.Repl;
|
|
||||||
using Microsoft.Repl.Commanding;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
using Microsoft.Repl.Parsing;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class ConfigCommand : CommandWithStructuredInputBase<HttpState, ICoreParseResult>
|
|
||||||
{
|
|
||||||
protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (programState.BaseAddress == null)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("Must be connected to a server to query configuration".SetColor(programState.ErrorColor));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(programState.DiagnosticsState.DiagnosticsEndpoint))
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("Diagnostics endpoint must be set to query configuration (see set diag)".SetColor(programState.ErrorColor));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string configUrl = programState.DiagnosticsState.DiagnosticItems.FirstOrDefault(x => x.DisplayName == "Configuration")?.Url;
|
|
||||||
|
|
||||||
if (configUrl == null)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("Diagnostics endpoint does not expose configuration information".SetColor(programState.ErrorColor));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpResponseMessage response = await programState.Client.GetAsync(new Uri(programState.BaseAddress, configUrl), cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("Unable to get configuration information from diagnostics endpoint".SetColor(programState.ErrorColor));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ConfigItem> configItems = await response.Content.ReadAsAsync<List<ConfigItem>>(cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
foreach (ConfigItem item in configItems)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.WriteLine($"{item.Key.Cyan()}: {item.Value}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("config").Finish();
|
|
||||||
|
|
||||||
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
return "config - Gets configuration information for the site if connected to a diagnostics endpoint";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetHelpSummary(IShellState shellState, HttpState programState)
|
|
||||||
{
|
|
||||||
return "config - Gets configuration information for the site if connected to a diagnostics endpoint";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class DeleteCommand : BaseHttpCommand
|
|
||||||
{
|
|
||||||
protected override string Verb => "delete";
|
|
||||||
|
|
||||||
protected override bool RequiresBody => false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Repl;
|
|
||||||
using Microsoft.Repl.Commanding;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
using Microsoft.Repl.Parsing;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class EchoCommand : CommandWithStructuredInputBase<HttpState, ICoreParseResult>
|
|
||||||
{
|
|
||||||
private readonly HashSet<string> _allowedModes = new HashSet<string>(StringComparer.OrdinalIgnoreCase) {"on", "off"};
|
|
||||||
|
|
||||||
protected override bool CanHandle(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput)
|
|
||||||
{
|
|
||||||
if (commandInput.Arguments.Count == 0 || !_allowedModes.Contains(commandInput.Arguments[0]?.Text))
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("Allowed echo modes are 'on' and 'off'".SetColor(programState.ErrorColor));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
bool turnOn = string.Equals(commandInput.Arguments[0].Text, "on", StringComparison.OrdinalIgnoreCase);
|
|
||||||
programState.EchoRequest = turnOn;
|
|
||||||
|
|
||||||
shellState.ConsoleManager.WriteLine("Request echoing is " + (turnOn ? "on" : "off"));
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("echo").ExactArgCount(1).Finish();
|
|
||||||
|
|
||||||
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
var helpText = new StringBuilder();
|
|
||||||
helpText.Append("Usage: ".Bold());
|
|
||||||
helpText.AppendLine($"echo [on|off]");
|
|
||||||
helpText.AppendLine();
|
|
||||||
helpText.AppendLine($"Turns request echoing on or off. When request echoing is on we will display a text representation of requests made by the CLI.");
|
|
||||||
return helpText.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetHelpSummary(IShellState shellState, HttpState programState)
|
|
||||||
{
|
|
||||||
return "echo [on/off] - Turns request echoing on or off";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override IEnumerable<string> GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput<ICoreParseResult> commandInput, string normalCompletionString)
|
|
||||||
{
|
|
||||||
List<string> result = _allowedModes.Where(x => x.StartsWith(normalCompletionString, StringComparison.OrdinalIgnoreCase)).ToList();
|
|
||||||
return result.Count > 0 ? result : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Repl;
|
|
||||||
using Microsoft.Repl.Commanding;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
using Microsoft.Repl.Parsing;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class ExitCommand : CommandWithStructuredInputBase<object, ICoreParseResult>
|
|
||||||
{
|
|
||||||
protected override Task ExecuteAsync(IShellState shellState, object programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
shellState.IsExiting = true;
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("exit").ExactArgCount(0).Finish();
|
|
||||||
|
|
||||||
protected override string GetHelpDetails(IShellState shellState, object programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
var helpText = new StringBuilder();
|
|
||||||
helpText.Append("Usage: ".Bold());
|
|
||||||
helpText.AppendLine($"exit");
|
|
||||||
helpText.AppendLine();
|
|
||||||
helpText.AppendLine($"Exits the shell");
|
|
||||||
return helpText.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetHelpSummary(IShellState shellState, object programState)
|
|
||||||
{
|
|
||||||
return "exit - Exits the shell";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class Formatter
|
|
||||||
{
|
|
||||||
private int _prefix;
|
|
||||||
private int _maxDepth;
|
|
||||||
|
|
||||||
public void RegisterEntry(int prefixLength, int depth)
|
|
||||||
{
|
|
||||||
if (depth > _maxDepth)
|
|
||||||
{
|
|
||||||
_maxDepth = depth;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prefixLength > _prefix)
|
|
||||||
{
|
|
||||||
_prefix = prefixLength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Format(string prefix, string entry, int level)
|
|
||||||
{
|
|
||||||
string indent = "".PadRight(level * 4);
|
|
||||||
return (indent + prefix).PadRight(_prefix + 3 + _maxDepth * 4) + entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class GetCommand : BaseHttpCommand
|
|
||||||
{
|
|
||||||
protected override string Verb => "get";
|
|
||||||
|
|
||||||
protected override bool RequiresBody => false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class HeadCommand : BaseHttpCommand
|
|
||||||
{
|
|
||||||
protected override string Verb => "head";
|
|
||||||
|
|
||||||
protected override bool RequiresBody => false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,256 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.HttpRepl.Preferences;
|
|
||||||
using Microsoft.HttpRepl.Suggestions;
|
|
||||||
using Microsoft.Repl;
|
|
||||||
using Microsoft.Repl.Commanding;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
using Microsoft.Repl.Parsing;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class HelpCommand : ICommand<HttpState, ICoreParseResult>
|
|
||||||
{
|
|
||||||
private static readonly string Name = "help";
|
|
||||||
|
|
||||||
public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
return parseResult.Sections.Count > 0 && string.Equals(parseResult.Sections[0], Name)
|
|
||||||
? (bool?)true
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (shellState.CommandDispatcher is ICommandDispatcher<HttpState, ICoreParseResult> dispatcher)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count == 1)
|
|
||||||
{
|
|
||||||
CoreGetHelp(shellState, dispatcher, programState);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool anyHelp = false;
|
|
||||||
|
|
||||||
if (parseResult.Slice(1) is ICoreParseResult continuationParseResult)
|
|
||||||
{
|
|
||||||
foreach (ICommand<HttpState, ICoreParseResult> command in dispatcher.Commands)
|
|
||||||
{
|
|
||||||
string help = command.GetHelpDetails(shellState, programState, continuationParseResult);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(help))
|
|
||||||
{
|
|
||||||
anyHelp = true;
|
|
||||||
shellState.ConsoleManager.WriteLine();
|
|
||||||
shellState.ConsoleManager.WriteLine(help);
|
|
||||||
|
|
||||||
var structuredCommand = command as CommandWithStructuredInputBase<HttpState, ICoreParseResult>;
|
|
||||||
if (structuredCommand != null && structuredCommand.InputSpec.Options.Any())
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.WriteLine();
|
|
||||||
shellState.ConsoleManager.WriteLine("Options:".Bold());
|
|
||||||
foreach (var option in structuredCommand.InputSpec.Options)
|
|
||||||
{
|
|
||||||
var optionText = string.Empty;
|
|
||||||
foreach (var form in option.Forms)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(optionText))
|
|
||||||
{
|
|
||||||
optionText += "|";
|
|
||||||
}
|
|
||||||
optionText += form;
|
|
||||||
}
|
|
||||||
shellState.ConsoleManager.WriteLine($" {optionText}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!anyHelp)
|
|
||||||
{
|
|
||||||
//Maybe the input is an URL
|
|
||||||
if (parseResult.Sections.Count == 2)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (programState.SwaggerEndpoint != null)
|
|
||||||
{
|
|
||||||
string swaggerRequeryBehaviorSetting = programState.GetStringPreference(WellKnownPreference.SwaggerRequeryBehavior, "auto");
|
|
||||||
|
|
||||||
if (swaggerRequeryBehaviorSetting.StartsWith("auto", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, programState, programState.SwaggerEndpoint, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Structure is null because, for example, SwaggerEndpoint exists but is not reachable.
|
|
||||||
if (programState.Structure != null)
|
|
||||||
{
|
|
||||||
IDirectoryStructure structure = programState.Structure.TraverseTo(parseResult.Sections[1]);
|
|
||||||
if (structure.DirectoryNames.Any())
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.WriteLine("Child directories:");
|
|
||||||
|
|
||||||
foreach (string name in structure.DirectoryNames)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.WriteLine(" " + name + "/");
|
|
||||||
}
|
|
||||||
anyHelp = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (structure.RequestInfo != null)
|
|
||||||
{
|
|
||||||
if (structure.RequestInfo.Methods.Count > 0)
|
|
||||||
{
|
|
||||||
if (anyHelp)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.WriteLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
anyHelp = true;
|
|
||||||
shellState.ConsoleManager.WriteLine("Available methods:");
|
|
||||||
|
|
||||||
foreach (string method in structure.RequestInfo.Methods)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.WriteLine(" " + method.ToUpperInvariant());
|
|
||||||
IReadOnlyList<string> accepts = structure.RequestInfo.ContentTypesByMethod[method];
|
|
||||||
string acceptsString = string.Join(", ", accepts.Where(x => !string.IsNullOrEmpty(x)));
|
|
||||||
if (!string.IsNullOrEmpty(acceptsString))
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.WriteLine(" Accepts: " + acceptsString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!anyHelp)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.WriteLine("Unable to locate any help information for the specified command");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count > 0 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count > 1)
|
|
||||||
{
|
|
||||||
return "Gets help about " + parseResult.Slice(1).CommandText;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return "Gets help";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpSummary(IShellState shellState, HttpState programState)
|
|
||||||
{
|
|
||||||
return "help - Gets help";
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
if (parseResult.SelectedSection == 0 &&
|
|
||||||
(string.IsNullOrEmpty(parseResult.Sections[parseResult.SelectedSection]) || Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
return new[] { Name };
|
|
||||||
}
|
|
||||||
else if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
if (shellState.CommandDispatcher is ICommandDispatcher<HttpState, ICoreParseResult> dispatcher
|
|
||||||
&& parseResult.Slice(1) is ICoreParseResult continuationParseResult)
|
|
||||||
{
|
|
||||||
HashSet<string> suggestions = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
foreach (ICommand<HttpState, ICoreParseResult> command in dispatcher.Commands)
|
|
||||||
{
|
|
||||||
IEnumerable<string> commandSuggestions = command.Suggest(shellState, programState, continuationParseResult);
|
|
||||||
|
|
||||||
if (commandSuggestions != null)
|
|
||||||
{
|
|
||||||
suggestions.UnionWith(commandSuggestions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (continuationParseResult.SelectedSection == 0)
|
|
||||||
{
|
|
||||||
string normalizedCompletionText = continuationParseResult.Sections[0].Substring(0, continuationParseResult.CaretPositionWithinSelectedSection);
|
|
||||||
suggestions.UnionWith(ServerPathCompletion.GetCompletions(programState, normalizedCompletionText));
|
|
||||||
}
|
|
||||||
|
|
||||||
return suggestions.OrderBy(x => x, StringComparer.OrdinalIgnoreCase).ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CoreGetHelp(IShellState shellState, ICommandDispatcher<HttpState, ICoreParseResult> dispatcher, HttpState programState)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.WriteLine();
|
|
||||||
shellState.ConsoleManager.WriteLine("HTTP Commands:".Bold().Cyan());
|
|
||||||
shellState.ConsoleManager.WriteLine("Use these commands to execute requests against your application.");
|
|
||||||
shellState.ConsoleManager.WriteLine();
|
|
||||||
|
|
||||||
const int navCommandColumn = -15;
|
|
||||||
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"GET",navCommandColumn}{"Issues a GET request."}");
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"POST",navCommandColumn}{"Issues a POST request."}");
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"PUT",navCommandColumn}{"Issues a PUT request."}");
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"DELETE",navCommandColumn}{"Issues a DELETE request."}");
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"PATCH",navCommandColumn}{"Issues a PATCH request."}");
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"HEAD",navCommandColumn}{"Issues a HEAD request."}");
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"OPTIONS",navCommandColumn}{"Issues an OPTIONS request."}");
|
|
||||||
shellState.ConsoleManager.WriteLine();
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"set header",navCommandColumn}{"Sets or clears a header for all requests. e.g. `set header content-type application/json`"}");
|
|
||||||
shellState.ConsoleManager.WriteLine();
|
|
||||||
|
|
||||||
shellState.ConsoleManager.WriteLine();
|
|
||||||
shellState.ConsoleManager.WriteLine("Navigation Commands:".Bold().Cyan());
|
|
||||||
shellState.ConsoleManager.WriteLine("The REPL allows you to navigate your URL space and focus on specific APIS that you are working on.");
|
|
||||||
shellState.ConsoleManager.WriteLine();
|
|
||||||
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"set base",navCommandColumn}{"Set the base URI. e.g. `set base http://locahost:5000`"}");
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"set swagger",navCommandColumn}{"Set the URI, relative to your base if set, of the Swagger document for this API. e.g. `set swagger /swagger/v1/swagger.json`"}");
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"ls",navCommandColumn}{"Show all endpoints for the current path."}");
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"cd",navCommandColumn}{"Append the given directory to the currently selected path, or move up a path when using `cd ..`."}");
|
|
||||||
|
|
||||||
shellState.ConsoleManager.WriteLine();
|
|
||||||
shellState.ConsoleManager.WriteLine("Shell Commands:".Bold().Cyan());
|
|
||||||
shellState.ConsoleManager.WriteLine("Use these commands to interact with the REPL shell.");
|
|
||||||
shellState.ConsoleManager.WriteLine();
|
|
||||||
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"clear",navCommandColumn}{"Removes all text from the shell."}");
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"echo [on/off]",navCommandColumn}{"Turns request echoing on or off, show the request that was mode when using request commands."}");
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"exit",navCommandColumn}{"Exit the shell."}");
|
|
||||||
|
|
||||||
shellState.ConsoleManager.WriteLine();
|
|
||||||
shellState.ConsoleManager.WriteLine("REPL Customization Commands:".Bold().Cyan());
|
|
||||||
shellState.ConsoleManager.WriteLine("Use these commands to customize the REPL behavior..");
|
|
||||||
shellState.ConsoleManager.WriteLine();
|
|
||||||
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"pref [get/set]",navCommandColumn}{"Allows viewing or changing preferences, e.g. 'pref set editor.command.default 'C:\\Program Files\\Microsoft VS Code\\Code.exe'`"}");
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"run",navCommandColumn}{"Runs the script at the given path. A script is a set of commands that can be typed with one command per line."}");
|
|
||||||
shellState.ConsoleManager.WriteLine($"{"ui",navCommandColumn}{"Displays the swagger UI page, if available, in the default browser."}");
|
|
||||||
shellState.ConsoleManager.WriteLine();
|
|
||||||
shellState.ConsoleManager.WriteLine("Use help <COMMAND> to learn more details about individual commands. e.g. `help get`".Bold().Cyan());
|
|
||||||
shellState.ConsoleManager.WriteLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,187 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.HttpRepl.Preferences;
|
|
||||||
using Microsoft.Repl;
|
|
||||||
using Microsoft.Repl.Commanding;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
using Microsoft.Repl.Parsing;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class ListCommand : CommandWithStructuredInputBase<HttpState, ICoreParseResult>
|
|
||||||
{
|
|
||||||
private const string RecursiveOption = nameof(RecursiveOption);
|
|
||||||
|
|
||||||
protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (programState.SwaggerEndpoint != null)
|
|
||||||
{
|
|
||||||
string swaggerRequeryBehaviorSetting = programState.GetStringPreference(WellKnownPreference.SwaggerRequeryBehavior, "auto");
|
|
||||||
|
|
||||||
if (swaggerRequeryBehaviorSetting.StartsWith("auto", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, programState, programState.SwaggerEndpoint, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (programState.Structure == null || programState.BaseAddress == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string path = commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty;
|
|
||||||
|
|
||||||
//If it's an absolute URI, nothing to suggest
|
|
||||||
if (Uri.TryCreate(path, UriKind.Absolute, out Uri _))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse()).TraverseTo(path);
|
|
||||||
|
|
||||||
string thisDirMethod = s.RequestInfo != null && s.RequestInfo.Methods.Count > 0
|
|
||||||
? "[" + string.Join("|", s.RequestInfo.Methods) + "]"
|
|
||||||
: "[]";
|
|
||||||
|
|
||||||
List<TreeNode> roots = new List<TreeNode>();
|
|
||||||
Formatter formatter = new Formatter();
|
|
||||||
|
|
||||||
roots.Add(new TreeNode(formatter, ".", thisDirMethod));
|
|
||||||
|
|
||||||
if (s.Parent != null)
|
|
||||||
{
|
|
||||||
string parentDirMethod = s.Parent.RequestInfo != null && s.Parent.RequestInfo.Methods.Count > 0
|
|
||||||
? "[" + string.Join("|", s.Parent.RequestInfo.Methods) + "]"
|
|
||||||
: "[]";
|
|
||||||
|
|
||||||
roots.Add(new TreeNode(formatter, "..", parentDirMethod));
|
|
||||||
}
|
|
||||||
|
|
||||||
int recursionDepth = 1;
|
|
||||||
|
|
||||||
if (commandInput.Options[RecursiveOption].Count > 0)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(commandInput.Options[RecursiveOption][0]?.Text))
|
|
||||||
{
|
|
||||||
recursionDepth = int.MaxValue;
|
|
||||||
}
|
|
||||||
else if (int.TryParse(commandInput.Options[RecursiveOption][0].Text, NumberStyles.Integer, CultureInfo.InvariantCulture, out int rd) && rd > 1)
|
|
||||||
{
|
|
||||||
recursionDepth = rd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (string child in s.DirectoryNames)
|
|
||||||
{
|
|
||||||
IDirectoryStructure dir = s.GetChildDirectory(child);
|
|
||||||
|
|
||||||
string methods = dir.RequestInfo != null && dir.RequestInfo.Methods.Count > 0
|
|
||||||
? "[" + string.Join("|", dir.RequestInfo.Methods) + "]"
|
|
||||||
: "[]";
|
|
||||||
|
|
||||||
TreeNode dirNode = new TreeNode(formatter, child, methods);
|
|
||||||
roots.Add(dirNode);
|
|
||||||
Recurse(dirNode, dir, recursionDepth - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (TreeNode node in roots)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.WriteLine(node.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Recurse(TreeNode parentNode, IDirectoryStructure parent, int remainingDepth)
|
|
||||||
{
|
|
||||||
if (remainingDepth <= 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (string child in parent.DirectoryNames)
|
|
||||||
{
|
|
||||||
IDirectoryStructure dir = parent.GetChildDirectory(child);
|
|
||||||
|
|
||||||
string methods = dir.RequestInfo != null && dir.RequestInfo.Methods.Count > 0
|
|
||||||
? "[" + string.Join("|", dir.RequestInfo.Methods) + "]"
|
|
||||||
: "[]";
|
|
||||||
|
|
||||||
TreeNode node = parentNode.AddChild(child, methods);
|
|
||||||
Recurse(node, dir, remainingDepth - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("ls").AlternateName("dir")
|
|
||||||
.MaximumArgCount(1)
|
|
||||||
.WithOption(new CommandOptionSpecification(RecursiveOption, maximumOccurrences: 1, acceptsValue: true, forms: new[] {"-r", "--recursive"}))
|
|
||||||
.Finish();
|
|
||||||
|
|
||||||
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
var helpText = new StringBuilder();
|
|
||||||
helpText.Append("Usage: ".Bold());
|
|
||||||
helpText.AppendLine($"ls [Options]");
|
|
||||||
helpText.AppendLine();
|
|
||||||
helpText.AppendLine($"Displays the known routes at the current location. Requires a Swagger document to be set.");
|
|
||||||
return helpText.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetHelpSummary(IShellState shellState, HttpState programState)
|
|
||||||
{
|
|
||||||
return "ls - List known routes for the current location";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override IEnumerable<string> GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput<ICoreParseResult> commandInput, string normalCompletionString)
|
|
||||||
{
|
|
||||||
if (programState.Structure == null || programState.BaseAddress == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//If it's an absolute URI, nothing to suggest
|
|
||||||
if (Uri.TryCreate(normalCompletionString, UriKind.Absolute, out Uri _))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
string path = normalCompletionString.Replace('\\', '/');
|
|
||||||
int searchFrom = normalCompletionString.Length - 1;
|
|
||||||
int lastSlash = path.LastIndexOf('/', searchFrom);
|
|
||||||
string prefix;
|
|
||||||
|
|
||||||
if (lastSlash < 0)
|
|
||||||
{
|
|
||||||
path = string.Empty;
|
|
||||||
prefix = normalCompletionString;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
path = path.Substring(0, lastSlash + 1);
|
|
||||||
prefix = normalCompletionString.Substring(lastSlash + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse()).TraverseTo(path);
|
|
||||||
|
|
||||||
List<string> results = new List<string>();
|
|
||||||
|
|
||||||
foreach (string child in s.DirectoryNames)
|
|
||||||
{
|
|
||||||
if (child.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
results.Add(path + child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class OptionsCommand : BaseHttpCommand
|
|
||||||
{
|
|
||||||
protected override string Verb => "options";
|
|
||||||
|
|
||||||
protected override bool RequiresBody => false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class PatchCommand : BaseHttpCommand
|
|
||||||
{
|
|
||||||
protected override string Verb => "patch";
|
|
||||||
|
|
||||||
protected override bool RequiresBody => true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class PostCommand : BaseHttpCommand
|
|
||||||
{
|
|
||||||
protected override string Verb => "post";
|
|
||||||
|
|
||||||
protected override bool RequiresBody => true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,243 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.HttpRepl.Preferences;
|
|
||||||
using Microsoft.Repl;
|
|
||||||
using Microsoft.Repl.Commanding;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
using Microsoft.Repl.Parsing;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class PrefCommand : CommandWithStructuredInputBase<HttpState, ICoreParseResult>
|
|
||||||
{
|
|
||||||
private readonly HashSet<string> _allowedSubcommands = new HashSet<string>(StringComparer.OrdinalIgnoreCase) {"get", "set"};
|
|
||||||
|
|
||||||
public override string GetHelpSummary(IShellState shellState, HttpState programState)
|
|
||||||
{
|
|
||||||
return "pref [get/set] {setting} [{value}] - Allows viewing or changing preferences";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool CanHandle(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput)
|
|
||||||
{
|
|
||||||
if (commandInput.Arguments.Count == 0 || !_allowedSubcommands.Contains(commandInput.Arguments[0]?.Text))
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("Whether get or set settings must be specified");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.Equals("get", commandInput.Arguments[0].Text) && (commandInput.Arguments.Count < 2 || string.IsNullOrEmpty(commandInput.Arguments[1]?.Text)))
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("The preference to set must be specified");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
var helpText = new StringBuilder();
|
|
||||||
helpText.Append("Usage: ".Bold());
|
|
||||||
|
|
||||||
if (commandInput.Arguments.Count == 0 || !_allowedSubcommands.Contains(commandInput.Arguments[0]?.Text))
|
|
||||||
{
|
|
||||||
helpText.AppendLine("pref [get/set] {setting} [{value}] - Get or sets a preference to a particular value");
|
|
||||||
}
|
|
||||||
else if (string.Equals(commandInput.Arguments[0].Text, "get", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
helpText.AppendLine("pref get [{setting}] - Gets the value of the specified preference or lists all preferences if no preference is specified");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
helpText.AppendLine("pref set {setting} [{value}] - Sets (or clears if value is not specified) the value of the specified preference");
|
|
||||||
}
|
|
||||||
|
|
||||||
helpText.AppendLine();
|
|
||||||
helpText.AppendLine("Current Default Preferences:");
|
|
||||||
foreach (var pref in programState.DefaultPreferences)
|
|
||||||
{
|
|
||||||
var val = pref.Value;
|
|
||||||
if (pref.Key.Contains("colors"))
|
|
||||||
{
|
|
||||||
val = GetColor(val);
|
|
||||||
}
|
|
||||||
helpText.AppendLine($"{pref.Key,-50}{val}");
|
|
||||||
}
|
|
||||||
helpText.AppendLine();
|
|
||||||
helpText.AppendLine("Current Preferences:");
|
|
||||||
foreach (var pref in programState.Preferences)
|
|
||||||
{
|
|
||||||
var val = pref.Value;
|
|
||||||
if (pref.Key.Contains("colors"))
|
|
||||||
{
|
|
||||||
val = GetColor(val);
|
|
||||||
}
|
|
||||||
helpText.AppendLine($"{pref.Key,-50}{val}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return helpText.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetColor(string value)
|
|
||||||
{
|
|
||||||
if (value.Contains("Bold"))
|
|
||||||
{
|
|
||||||
value = value.Bold();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.Contains("Yellow"))
|
|
||||||
{
|
|
||||||
value = value.Yellow();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.Contains("Cyan"))
|
|
||||||
{
|
|
||||||
value = value.Cyan();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.Contains("Magenta"))
|
|
||||||
{
|
|
||||||
value = value.Magenta();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.Contains("Green"))
|
|
||||||
{
|
|
||||||
value = value.Green();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.Contains("White"))
|
|
||||||
{
|
|
||||||
value = value.White();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.Contains("Black"))
|
|
||||||
{
|
|
||||||
value = value.Black();
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (string.Equals(commandInput.Arguments[0].Text, "get", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return GetSetting(shellState, programState, commandInput);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SetSetting(shellState, programState, commandInput);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Task SetSetting(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput)
|
|
||||||
{
|
|
||||||
string prefName = commandInput.Arguments[1].Text;
|
|
||||||
string prefValue = commandInput.Arguments.Count > 2 ? commandInput.Arguments[2]?.Text : null;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(prefValue))
|
|
||||||
{
|
|
||||||
if (!programState.DefaultPreferences.TryGetValue(prefName, out string defaultValue))
|
|
||||||
{
|
|
||||||
programState.Preferences.Remove(prefName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
programState.Preferences[prefName] = defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
programState.Preferences[prefName] = prefValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!programState.SavePreferences())
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("Error saving preferences".SetColor(programState.ErrorColor));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Task GetSetting(IShellState shellState, HttpState programState, DefaultCommandInput<ICoreParseResult> commandInput)
|
|
||||||
{
|
|
||||||
string preferenceName = commandInput.Arguments.Count > 1 ? commandInput.Arguments[1]?.Text : null;
|
|
||||||
|
|
||||||
//If there's a particular setting to get the value of
|
|
||||||
if (!string.IsNullOrEmpty(preferenceName))
|
|
||||||
{
|
|
||||||
if (programState.Preferences.TryGetValue(preferenceName, out string value))
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.WriteLine("Configured value: " + value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine((commandInput.Arguments[1].Text + " does not have a configured value").SetColor(programState.ErrorColor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (KeyValuePair<string, string> entry in programState.Preferences.OrderBy(x => x.Key))
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.WriteLine($"{entry.Key}={entry.Value}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("pref")
|
|
||||||
.MinimumArgCount(1)
|
|
||||||
.MaximumArgCount(3)
|
|
||||||
.Finish();
|
|
||||||
|
|
||||||
|
|
||||||
protected override IEnumerable<string> GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput<ICoreParseResult> commandInput, string normalCompletionString)
|
|
||||||
{
|
|
||||||
if (parseResult.SelectedSection == 1)
|
|
||||||
{
|
|
||||||
return _allowedSubcommands.Where(x => x.StartsWith(normalCompletionString, StringComparison.OrdinalIgnoreCase));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseResult.SelectedSection == 2)
|
|
||||||
{
|
|
||||||
string prefix = parseResult.Sections.Count > 2 ? normalCompletionString : string.Empty;
|
|
||||||
List<string> matchingProperties = new List<string>();
|
|
||||||
|
|
||||||
foreach (string val in WellKnownPreference.Catalog.Names)
|
|
||||||
{
|
|
||||||
if (val.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
matchingProperties.Add(val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return matchingProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseResult.SelectedSection == 3
|
|
||||||
&& parseResult.Sections[2].StartsWith("colors.", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
string prefix = parseResult.Sections.Count > 3 ? normalCompletionString : string.Empty;
|
|
||||||
List<string> matchingProperties = new List<string>();
|
|
||||||
|
|
||||||
foreach (string val in Enum.GetNames(typeof(AllowedColors)))
|
|
||||||
{
|
|
||||||
if (val.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
matchingProperties.Add(val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return matchingProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class PutCommand : BaseHttpCommand
|
|
||||||
{
|
|
||||||
protected override string Verb => "put";
|
|
||||||
|
|
||||||
protected override bool RequiresBody => true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Repl;
|
|
||||||
using Microsoft.Repl.Commanding;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
using Microsoft.Repl.Parsing;
|
|
||||||
using Microsoft.Repl.Scripting;
|
|
||||||
using Microsoft.Repl.Suggestions;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class RunCommand : ICommand<HttpState, ICoreParseResult>
|
|
||||||
{
|
|
||||||
private static readonly string Name = "run";
|
|
||||||
|
|
||||||
public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
return parseResult.Sections.Count > 1 && parseResult.Sections.Count < 4 && string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase)
|
|
||||||
? (bool?)true
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (!File.Exists(parseResult.Sections[1]))
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine($"Could not file script file {parseResult.Sections[1]}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool suppressScriptLinesInHistory = true;
|
|
||||||
if (parseResult.Sections.Count == 3)
|
|
||||||
{
|
|
||||||
suppressScriptLinesInHistory = !string.Equals(parseResult.Sections[2], "+history");
|
|
||||||
}
|
|
||||||
|
|
||||||
string[] lines = File.ReadAllLines(parseResult.Sections[1]);
|
|
||||||
IScriptExecutor scriptExecutor = new ScriptExecutor<HttpState, ICoreParseResult>(suppressScriptLinesInHistory);
|
|
||||||
await scriptExecutor.ExecuteScriptAsync(shellState, lines, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count > 0 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
var helpText = new StringBuilder();
|
|
||||||
helpText.Append("Usage: ".Bold());
|
|
||||||
helpText.AppendLine("run {path to script}");
|
|
||||||
helpText.AppendLine();
|
|
||||||
helpText.AppendLine("Runs the specified script.");
|
|
||||||
helpText.AppendLine("A script is a text file containing one CLI command per line. Each line will be run as if it was typed into the CLI.");
|
|
||||||
return helpText.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpSummary(IShellState shellState, HttpState programState)
|
|
||||||
{
|
|
||||||
return "run {path to script} - Runs a script";
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
if (parseResult.SelectedSection == 0 &&
|
|
||||||
(string.IsNullOrEmpty(parseResult.Sections[parseResult.SelectedSection]) || Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
return new[] { Name };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseResult.SelectedSection == 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return FileSystemCompletion.GetCompletions(parseResult.Sections[1].Substring(0, parseResult.CaretPositionWithinSelectedSection));
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Repl;
|
|
||||||
using Microsoft.Repl.Commanding;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
using Microsoft.Repl.Parsing;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class SetBaseCommand : ICommand<HttpState, ICoreParseResult>
|
|
||||||
{
|
|
||||||
private const string Name = "set";
|
|
||||||
private const string SubCommand = "base";
|
|
||||||
|
|
||||||
public string Description => "Sets the base address to direct requests to.";
|
|
||||||
|
|
||||||
public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
return parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase)
|
|
||||||
? (bool?)true
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ExecuteAsync(IShellState shellState, HttpState state, ICoreParseResult parseResult, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count == 2)
|
|
||||||
{
|
|
||||||
state.BaseAddress = null;
|
|
||||||
}
|
|
||||||
else if (parseResult.Sections.Count != 3 || string.IsNullOrEmpty(parseResult.Sections[2]) || !Uri.TryCreate(EnsureTrailingSlash(parseResult.Sections[2]), UriKind.Absolute, out Uri serverUri))
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("Must specify a server".SetColor(state.ErrorColor));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state.BaseAddress = serverUri;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await state.Client.SendAsync(new HttpRequestMessage(HttpMethod.Head, serverUri)).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex) when (ex.InnerException is SocketException se)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine($"Warning: HEAD request to the specified address was unsuccessful ({se.Message})".SetColor(state.WarningColor));
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.BaseAddress == null || !Uri.TryCreate(state.BaseAddress, "swagger.json", out Uri result))
|
|
||||||
{
|
|
||||||
state.SwaggerStructure = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, state, result, cancellationToken).ConfigureAwait(false);
|
|
||||||
if (state.SwaggerStructure != null)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.WriteLine("Using swagger metadata from " + result);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (state.BaseAddress == null || !Uri.TryCreate(state.BaseAddress, "swagger/v1/swagger.json", out result))
|
|
||||||
{
|
|
||||||
state.SwaggerStructure = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, state, result, cancellationToken).ConfigureAwait(false);
|
|
||||||
if (state.SwaggerStructure != null)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.WriteLine("Using swagger metadata from " + result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string EnsureTrailingSlash(string v)
|
|
||||||
{
|
|
||||||
if (!v.EndsWith("/", StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
v += "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
var helpText = new StringBuilder();
|
|
||||||
helpText.Append("Usage: ".Bold());
|
|
||||||
helpText.AppendLine($"set base [uri]");
|
|
||||||
helpText.AppendLine();
|
|
||||||
helpText.AppendLine(Description);
|
|
||||||
return helpText.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpSummary(IShellState shellState, HttpState programState)
|
|
||||||
{
|
|
||||||
return Description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count == 0)
|
|
||||||
{
|
|
||||||
return new[] { Name };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseResult.Sections.Count > 0 && parseResult.SelectedSection == 0 && Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return new[] { Name };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 1 && (parseResult.Sections.Count < 2 || SubCommand.StartsWith(parseResult.Sections[1].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
return new[] { SubCommand };
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,141 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.HttpRepl.Diagnostics;
|
|
||||||
using Microsoft.Repl;
|
|
||||||
using Microsoft.Repl.Commanding;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
using Microsoft.Repl.Parsing;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class SetDiagCommand : ICommand<HttpState, ICoreParseResult>
|
|
||||||
{
|
|
||||||
private static readonly string Name = "set";
|
|
||||||
private static readonly string SubCommand = "diag";
|
|
||||||
|
|
||||||
public string Description => "Sets the diagnostics path to direct requests to.";
|
|
||||||
|
|
||||||
public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
return parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase)
|
|
||||||
? (bool?)true
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count == 2)
|
|
||||||
{
|
|
||||||
programState.DiagnosticsState.DiagnosticsEndpoint = null;
|
|
||||||
programState.DiagnosticsState.DiagnosticItems = null;
|
|
||||||
programState.DiagnosticsState.DiagEndpointsStructure = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseResult.Sections.Count != 3 || string.IsNullOrEmpty(parseResult.Sections[2]) || !Uri.TryCreate(parseResult.Sections[2], UriKind.Relative, out Uri _))
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("Must specify a relative path".SetColor(programState.ErrorColor));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
programState.DiagnosticsState.DiagnosticsEndpoint = parseResult.Sections[2];
|
|
||||||
HttpResponseMessage response = await programState.Client.GetAsync(new Uri(programState.BaseAddress, programState.DiagnosticsState.DiagnosticsEndpoint), cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("Unable to access diagnostics endpoint".SetColor(programState.ErrorColor));
|
|
||||||
programState.DiagnosticsState.DiagnosticsEndpoint = null;
|
|
||||||
programState.DiagnosticsState.DiagnosticItems = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
programState.DiagnosticsState.DiagnosticItems = (await response.Content.ReadAsAsync<Dictionary<string, DiagItem>>(cancellationToken).ConfigureAwait(false))?.Select(x => x.Value).ToList();
|
|
||||||
|
|
||||||
DiagItem endpointsItem = programState.DiagnosticsState.DiagnosticItems?.FirstOrDefault(x => string.Equals(x.DisplayName, "Endpoints", StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
if (endpointsItem != null)
|
|
||||||
{
|
|
||||||
HttpResponseMessage endpointsResponse = await programState.Client.GetAsync(new Uri(programState.BaseAddress, endpointsItem.Url), cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (!endpointsResponse.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("Unable to get endpoints information from diagnostics endpoint".SetColor(programState.ErrorColor));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<DiagEndpoint> endpoints = await endpointsResponse.Content.ReadAsAsync<List<DiagEndpoint>>(cancellationToken).ConfigureAwait(false);
|
|
||||||
DirectoryStructure structure = new DirectoryStructure(null);
|
|
||||||
|
|
||||||
foreach (DiagEndpoint endpoint in endpoints)
|
|
||||||
{
|
|
||||||
if (endpoint.Url.StartsWith(endpointsItem.Url, StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| endpoint.Url.StartsWith("/graphql", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
FillDirectoryInfo(structure, endpoint.Url);
|
|
||||||
}
|
|
||||||
|
|
||||||
programState.DiagnosticsState.DiagEndpointsStructure = structure;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void FillDirectoryInfo(DirectoryStructure parent, string endpoint)
|
|
||||||
{
|
|
||||||
string[] parts = endpoint.Split('/');
|
|
||||||
|
|
||||||
foreach (string part in parts)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(part))
|
|
||||||
{
|
|
||||||
parent = parent.DeclareDirectory(part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpSummary(IShellState shellState, HttpState programState)
|
|
||||||
{
|
|
||||||
return Description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return Description;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count == 0)
|
|
||||||
{
|
|
||||||
return new[] { Name };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseResult.Sections.Count > 0 && parseResult.SelectedSection == 0 && Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return new[] { Name };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 1 && (parseResult.Sections.Count < 2 || SubCommand.StartsWith(parseResult.Sections[1].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
return new[] { SubCommand };
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.HttpRepl.Suggestions;
|
|
||||||
using Microsoft.Repl;
|
|
||||||
using Microsoft.Repl.Commanding;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
using Microsoft.Repl.Parsing;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class SetHeaderCommand : ICommand<HttpState, ICoreParseResult>
|
|
||||||
{
|
|
||||||
private static readonly string Name = "set";
|
|
||||||
private static readonly string SubCommand = "header";
|
|
||||||
|
|
||||||
public string Description => "set header {name} [value] - Sets or clears a header";
|
|
||||||
|
|
||||||
public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
return parseResult.Sections.Count > 2 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase)
|
|
||||||
? (bool?)true
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count == 3)
|
|
||||||
{
|
|
||||||
programState.Headers.Remove(parseResult.Sections[2]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
programState.Headers[parseResult.Sections[2]] = parseResult.Sections.Skip(3).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
var helpText = new StringBuilder();
|
|
||||||
helpText.Append("Usage: ".Bold());
|
|
||||||
helpText.AppendLine("set header {name} [value]");
|
|
||||||
helpText.AppendLine();
|
|
||||||
helpText.AppendLine("Sets or clears a header. When [value] is empty the header is cleared.");
|
|
||||||
return Description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpSummary(IShellState shellState, HttpState programState)
|
|
||||||
{
|
|
||||||
return Description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count == 0)
|
|
||||||
{
|
|
||||||
return new[] { Name };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseResult.Sections.Count > 0 && parseResult.SelectedSection == 0 && Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return new[] { Name };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 1 && (parseResult.Sections.Count < 2 || SubCommand.StartsWith(parseResult.Sections[1].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
return new[] { SubCommand };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseResult.Sections.Count > 2
|
|
||||||
&& string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase)
|
|
||||||
&& string.Equals(SubCommand, parseResult.Sections[1], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 2)
|
|
||||||
{
|
|
||||||
string prefix = parseResult.Sections[2].Substring(0, parseResult.CaretPositionWithinSelectedSection);
|
|
||||||
return HeaderCompletion.GetCompletions(null, prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseResult.Sections.Count > 3
|
|
||||||
&& string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase)
|
|
||||||
&& string.Equals(SubCommand, parseResult.Sections[1], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 3)
|
|
||||||
{
|
|
||||||
string prefix = parseResult.Sections[3].Substring(0, parseResult.CaretPositionWithinSelectedSection);
|
|
||||||
return HeaderCompletion.GetValueCompletions(null, string.Empty, parseResult.Sections[2], prefix, programState);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,277 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.HttpRepl.OpenApi;
|
|
||||||
using Microsoft.Repl;
|
|
||||||
using Microsoft.Repl.Commanding;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
using Microsoft.Repl.Parsing;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class SetSwaggerCommand : ICommand<HttpState, ICoreParseResult>
|
|
||||||
{
|
|
||||||
private static readonly string Name = "set";
|
|
||||||
private static readonly string SubCommand = "swagger";
|
|
||||||
|
|
||||||
public string Description => "Sets the swagger document to use for information about the current server";
|
|
||||||
|
|
||||||
private static void FillDirectoryInfo(DirectoryStructure parent, EndpointMetadata entry)
|
|
||||||
{
|
|
||||||
string[] parts = entry.Path.Split('/');
|
|
||||||
|
|
||||||
foreach (string part in parts)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(part))
|
|
||||||
{
|
|
||||||
parent = parent.DeclareDirectory(part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RequestInfo dirRequestInfo = new RequestInfo();
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>> requestInfo in entry.AvailableRequests)
|
|
||||||
{
|
|
||||||
string method = requestInfo.Key;
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, IReadOnlyList<Parameter>> parameterSetsByContentType in requestInfo.Value)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(parameterSetsByContentType.Key))
|
|
||||||
{
|
|
||||||
dirRequestInfo.SetFallbackRequestBody(method, parameterSetsByContentType.Key, GetBodyString(null, parameterSetsByContentType.Value));
|
|
||||||
}
|
|
||||||
|
|
||||||
dirRequestInfo.SetRequestBody(method, parameterSetsByContentType.Key, GetBodyString(parameterSetsByContentType.Key, parameterSetsByContentType.Value));
|
|
||||||
}
|
|
||||||
|
|
||||||
dirRequestInfo.AddMethod(method);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dirRequestInfo.Methods.Count > 0)
|
|
||||||
{
|
|
||||||
parent.RequestInfo = dirRequestInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetBodyString(string contentType, IEnumerable<Parameter> operation)
|
|
||||||
{
|
|
||||||
Parameter body = operation.FirstOrDefault(x => string.Equals(x.Location, "body", StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
if (body != null)
|
|
||||||
{
|
|
||||||
JToken result = GenerateData(body.Schema);
|
|
||||||
return result?.ToString() ?? "{\n}";
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JToken GenerateData(Schema schema)
|
|
||||||
{
|
|
||||||
if (schema == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (schema.Example != null)
|
|
||||||
{
|
|
||||||
return JToken.FromObject(schema.Example);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (schema.Default != null)
|
|
||||||
{
|
|
||||||
return JToken.FromObject(schema.Default);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (schema.Type is null)
|
|
||||||
{
|
|
||||||
if (schema.Properties != null || schema.AdditionalProperties != null || schema.MinProperties.HasValue || schema.MaxProperties.HasValue)
|
|
||||||
{
|
|
||||||
schema.Type = "OBJECT";
|
|
||||||
}
|
|
||||||
else if (schema.Items != null || schema.MinItems.HasValue || schema.MaxItems.HasValue)
|
|
||||||
{
|
|
||||||
schema.Type = "ARRAY";
|
|
||||||
}
|
|
||||||
else if (schema.Minimum.HasValue || schema.Maximum.HasValue || schema.MultipleOf.HasValue)
|
|
||||||
{
|
|
||||||
schema.Type = "INTEGER";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (schema.Type?.ToUpperInvariant())
|
|
||||||
{
|
|
||||||
case null:
|
|
||||||
case "STRING":
|
|
||||||
return "";
|
|
||||||
case "NUMBER":
|
|
||||||
if (schema.Minimum.HasValue)
|
|
||||||
{
|
|
||||||
if (schema.Maximum.HasValue)
|
|
||||||
{
|
|
||||||
return (schema.Maximum.Value + schema.Minimum.Value) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (schema.ExclusiveMinimum)
|
|
||||||
{
|
|
||||||
return schema.Minimum.Value + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return schema.Minimum.Value;
|
|
||||||
}
|
|
||||||
return 1.1;
|
|
||||||
case "INTEGER":
|
|
||||||
if (schema.Minimum.HasValue)
|
|
||||||
{
|
|
||||||
if (schema.Maximum.HasValue)
|
|
||||||
{
|
|
||||||
return (int)((schema.Maximum.Value + schema.Minimum.Value) / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (schema.ExclusiveMinimum)
|
|
||||||
{
|
|
||||||
return schema.Minimum.Value + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return schema.Minimum.Value;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
case "BOOLEAN":
|
|
||||||
return true;
|
|
||||||
case "ARRAY":
|
|
||||||
JArray container = new JArray();
|
|
||||||
JToken item = GenerateData(schema.Items) ?? "";
|
|
||||||
|
|
||||||
int count = schema.MinItems.GetValueOrDefault();
|
|
||||||
count = Math.Max(1, count);
|
|
||||||
|
|
||||||
for (int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
container.Add(item.DeepClone());
|
|
||||||
}
|
|
||||||
|
|
||||||
return container;
|
|
||||||
case "OBJECT":
|
|
||||||
JObject obj = new JObject();
|
|
||||||
foreach (KeyValuePair<string, Schema> property in schema.Properties)
|
|
||||||
{
|
|
||||||
JToken data = GenerateData(property.Value) ?? "";
|
|
||||||
obj[property.Key] = data;
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<IEnumerable<EndpointMetadata>> GetSwaggerDocAsync(HttpClient client, Uri uri)
|
|
||||||
{
|
|
||||||
var resp = await client.GetAsync(uri).ConfigureAwait(false);
|
|
||||||
resp.EnsureSuccessStatusCode();
|
|
||||||
string responseString = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
|
||||||
JsonSerializer serializer = new JsonSerializer{ PreserveReferencesHandling = PreserveReferencesHandling.All };
|
|
||||||
JObject responseObject = (JObject)serializer.Deserialize(new StringReader(responseString), typeof(JObject));
|
|
||||||
EndpointMetadataReader reader = new EndpointMetadataReader();
|
|
||||||
responseObject = await PointerUtil.ResolvePointersAsync(uri, responseObject, client).ConfigureAwait(false) as JObject;
|
|
||||||
|
|
||||||
if (responseObject is null)
|
|
||||||
{
|
|
||||||
return new EndpointMetadata[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return reader.Read(responseObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpSummary(IShellState shellState, HttpState programState)
|
|
||||||
{
|
|
||||||
return Description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return Description;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count == 0)
|
|
||||||
{
|
|
||||||
return new[] { Name };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseResult.Sections.Count > 0 && parseResult.SelectedSection == 0 && Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return new[] { Name };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 1 && (parseResult.Sections.Count < 2 || SubCommand.StartsWith(parseResult.Sections[1].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
return new[] { SubCommand };
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
return parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase)
|
|
||||||
? (bool?)true
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count == 2)
|
|
||||||
{
|
|
||||||
programState.SwaggerStructure = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseResult.Sections.Count != 3 || string.IsNullOrEmpty(parseResult.Sections[2]) || !Uri.TryCreate(parseResult.Sections[2], UriKind.Absolute, out Uri serverUri))
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("Must specify a swagger document".SetColor(programState.ErrorColor));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await CreateDirectoryStructureForSwaggerEndpointAsync(shellState, programState, serverUri, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static async Task CreateDirectoryStructureForSwaggerEndpointAsync(IShellState shellState, HttpState programState, Uri serverUri, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
programState.SwaggerEndpoint = serverUri;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
IEnumerable<EndpointMetadata> doc = await GetSwaggerDocAsync(programState.Client, serverUri).ConfigureAwait(false);
|
|
||||||
|
|
||||||
DirectoryStructure d = new DirectoryStructure(null);
|
|
||||||
|
|
||||||
foreach (EndpointMetadata entry in doc)
|
|
||||||
{
|
|
||||||
FillDirectoryInfo(d, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
programState.SwaggerStructure = !cancellationToken.IsCancellationRequested ? d : null;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
programState.SwaggerStructure = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class TreeNode
|
|
||||||
{
|
|
||||||
private readonly int _depth;
|
|
||||||
private readonly Formatter _formatter;
|
|
||||||
private readonly string _prefix;
|
|
||||||
private readonly string _entry;
|
|
||||||
private readonly List<TreeNode> _children = new List<TreeNode>();
|
|
||||||
|
|
||||||
public TreeNode(Formatter formatter, string prefix, string entry)
|
|
||||||
: this(formatter, prefix, entry, 0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private TreeNode(Formatter formatter, string prefix, string entry, int depth)
|
|
||||||
{
|
|
||||||
_formatter = formatter;
|
|
||||||
formatter.RegisterEntry(prefix.Length, depth);
|
|
||||||
_prefix = prefix;
|
|
||||||
_entry = entry;
|
|
||||||
_depth = depth;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TreeNode AddChild(string prefix, string entry)
|
|
||||||
{
|
|
||||||
TreeNode child = new TreeNode(_formatter, prefix, entry, _depth + 1);
|
|
||||||
_children.Add(child);
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
string self = _formatter.Format(_prefix, _entry, _depth);
|
|
||||||
|
|
||||||
if (_children.Count == 0)
|
|
||||||
{
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
return self + Environment.NewLine + string.Join(Environment.NewLine, _children);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Repl;
|
|
||||||
using Microsoft.Repl.Commanding;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
using Microsoft.Repl.Parsing;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Commands
|
|
||||||
{
|
|
||||||
public class UICommand : ICommand<HttpState, ICoreParseResult>
|
|
||||||
{
|
|
||||||
private static readonly string Name = "ui";
|
|
||||||
|
|
||||||
public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
return parseResult.Sections.Count == 1 && string.Equals(parseResult.Sections[0], Name)
|
|
||||||
? (bool?)true
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (programState.BaseAddress == null)
|
|
||||||
{
|
|
||||||
shellState.ConsoleManager.Error.WriteLine("Must be connected to a server to launch Swagger UI".SetColor(programState.ErrorColor));
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
Uri uri = new Uri(programState.BaseAddress, "swagger");
|
|
||||||
string agent = "cmd";
|
|
||||||
string agentParam = $"/c start {uri.AbsoluteUri}";
|
|
||||||
|
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
|
||||||
{
|
|
||||||
agent = "open";
|
|
||||||
agentParam = uri.AbsoluteUri;
|
|
||||||
}
|
|
||||||
else if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
||||||
{
|
|
||||||
agent = "xdg-open";
|
|
||||||
agentParam = uri.AbsoluteUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
Process.Start(new ProcessStartInfo(agent, agentParam) { CreateNoWindow = true });
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
if (parseResult.Sections.Count == 1 && string.Equals(parseResult.Sections[0], Name))
|
|
||||||
{
|
|
||||||
return "ui - Launches the Swagger UI page (if available) in the default browser";
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHelpSummary(IShellState shellState, HttpState programState)
|
|
||||||
{
|
|
||||||
return "ui - Launches the Swagger UI page (if available) in the default browser";
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult)
|
|
||||||
{
|
|
||||||
if (parseResult.SelectedSection == 0 &&
|
|
||||||
(string.IsNullOrEmpty(parseResult.Sections[parseResult.SelectedSection]) || Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
return new[] { Name };
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Diagnostics
|
|
||||||
{
|
|
||||||
public class ConfigItem
|
|
||||||
{
|
|
||||||
public string Key { get; set; }
|
|
||||||
|
|
||||||
public string Value { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Diagnostics
|
|
||||||
{
|
|
||||||
public class DiagEndpoint
|
|
||||||
{
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
public string Url { get; set; }
|
|
||||||
public DiagEndpointMetadata[] Metadata { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Diagnostics
|
|
||||||
{
|
|
||||||
public class DiagEndpointMetadata
|
|
||||||
{
|
|
||||||
public object Item { get; set; }
|
|
||||||
public string Type { get; set; }
|
|
||||||
public string[] Interfaces { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Diagnostics
|
|
||||||
{
|
|
||||||
public class DiagItem
|
|
||||||
{
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
|
|
||||||
public string Description { get; set; }
|
|
||||||
|
|
||||||
public string Url { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Diagnostics
|
|
||||||
{
|
|
||||||
public class DiagnosticsState
|
|
||||||
{
|
|
||||||
public string DiagnosticsEndpoint { get; set; }
|
|
||||||
|
|
||||||
public IReadOnlyList<DiagItem> DiagnosticItems { get; internal set; }
|
|
||||||
|
|
||||||
public IDirectoryStructure DiagEndpointsStructure { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,115 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl
|
|
||||||
{
|
|
||||||
public class DirectoryStructure : IDirectoryStructure
|
|
||||||
{
|
|
||||||
private readonly Dictionary<string, DirectoryStructure> _childDirectories = new Dictionary<string, DirectoryStructure>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
public DirectoryStructure(IDirectoryStructure parent)
|
|
||||||
{
|
|
||||||
Parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> DirectoryNames => _childDirectories.Keys;
|
|
||||||
|
|
||||||
public IDirectoryStructure Parent { get; }
|
|
||||||
|
|
||||||
public DirectoryStructure DeclareDirectory(string name)
|
|
||||||
{
|
|
||||||
if (_childDirectories.TryGetValue(name, out DirectoryStructure existing))
|
|
||||||
{
|
|
||||||
return existing;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _childDirectories[name] = new DirectoryStructure(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDirectoryStructure GetChildDirectory(string name)
|
|
||||||
{
|
|
||||||
if (_childDirectories.TryGetValue(name, out DirectoryStructure result))
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
IDirectoryStructure parameterizedTarget = _childDirectories.FirstOrDefault(x => x.Key.StartsWith('{') && x.Key.EndsWith('}')).Value;
|
|
||||||
|
|
||||||
if (!(parameterizedTarget is null))
|
|
||||||
{
|
|
||||||
return parameterizedTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new DirectoryStructure(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IRequestInfo RequestInfo { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RequestInfo : IRequestInfo
|
|
||||||
{
|
|
||||||
private readonly HashSet<string> _methods = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
private readonly Dictionary<string, Dictionary<string, string>> _requestBodiesByMethodByContentType = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
private readonly Dictionary<string, string> _fallbackBodyStringsByMethod = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
private readonly Dictionary<string, string> _fallbackContentTypeStringsByMethod = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
private readonly Dictionary<string, IReadOnlyList<string>> _contentTypesByMethod = new Dictionary<string, IReadOnlyList<string>>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
public IReadOnlyList<string> Methods => _methods.ToList();
|
|
||||||
|
|
||||||
public IReadOnlyDictionary<string, IReadOnlyList<string>> ContentTypesByMethod => _contentTypesByMethod;
|
|
||||||
|
|
||||||
public string GetRequestBodyForContentType(ref string contentType, string method)
|
|
||||||
{
|
|
||||||
if (_requestBodiesByMethodByContentType.TryGetValue(method, out Dictionary<string, string> bodiesByContentType)
|
|
||||||
&& bodiesByContentType.TryGetValue(contentType, out string body))
|
|
||||||
{
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_fallbackBodyStringsByMethod.TryGetValue(method, out body))
|
|
||||||
{
|
|
||||||
if (_fallbackContentTypeStringsByMethod.TryGetValue(method, out string newContentType))
|
|
||||||
{
|
|
||||||
contentType = newContentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetRequestBody(string method, string contentType, string body)
|
|
||||||
{
|
|
||||||
if (!_requestBodiesByMethodByContentType.TryGetValue(method, out Dictionary<string, string> bodiesByContentType))
|
|
||||||
{
|
|
||||||
_requestBodiesByMethodByContentType[method] = bodiesByContentType = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_contentTypesByMethod.TryGetValue(method, out IReadOnlyList<string> contentTypesRaw))
|
|
||||||
{
|
|
||||||
_contentTypesByMethod[method] = contentTypesRaw = new List<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<string> contentTypes = (List<string>)contentTypesRaw;
|
|
||||||
contentTypes.Add(contentType);
|
|
||||||
|
|
||||||
bodiesByContentType[contentType] = body;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddMethod(string method)
|
|
||||||
{
|
|
||||||
_methods.Add(method);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetFallbackRequestBody(string method, string contentType, string fallbackBodyString)
|
|
||||||
{
|
|
||||||
_fallbackBodyStringsByMethod[method] = fallbackBodyString;
|
|
||||||
_fallbackContentTypeStringsByMethod[method] = contentType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl
|
|
||||||
{
|
|
||||||
public static class DirectoryStructureExtensions
|
|
||||||
{
|
|
||||||
public static IEnumerable<string> GetDirectoryListingAtPath(this IDirectoryStructure structure, string path)
|
|
||||||
{
|
|
||||||
return structure.TraverseTo(path).DirectoryNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IDirectoryStructure TraverseTo(this IDirectoryStructure structure, string path)
|
|
||||||
{
|
|
||||||
string[] parts = path.Replace('\\', '/').Split('/');
|
|
||||||
return structure.TraverseTo(parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IDirectoryStructure TraverseTo(this IDirectoryStructure structure, IEnumerable<string> pathParts)
|
|
||||||
{
|
|
||||||
IDirectoryStructure s = structure;
|
|
||||||
IReadOnlyList<string> parts = pathParts.ToList();
|
|
||||||
|
|
||||||
if (parts.Count == 0)
|
|
||||||
{
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parts[0] == string.Empty && parts.Count > 1)
|
|
||||||
{
|
|
||||||
while (s.Parent != null)
|
|
||||||
{
|
|
||||||
s = s.Parent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (string part in parts)
|
|
||||||
{
|
|
||||||
if (part == ".")
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (part == "..")
|
|
||||||
{
|
|
||||||
s = s.Parent ?? s;
|
|
||||||
}
|
|
||||||
else if (!string.IsNullOrEmpty(part))
|
|
||||||
{
|
|
||||||
s = s.GetChildDirectory(part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,114 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using Microsoft.HttpRepl.Preferences;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Formatting
|
|
||||||
{
|
|
||||||
public static class JsonVisitor
|
|
||||||
{
|
|
||||||
public static string FormatAndColorize(IJsonConfig config, string jsonData)
|
|
||||||
{
|
|
||||||
if (jsonData == null)
|
|
||||||
{
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
JsonTextReader reader = new JsonTextReader(new StringReader(jsonData));
|
|
||||||
bool isValuePosition = false;
|
|
||||||
bool isTerminalValue = false;
|
|
||||||
bool isFirstToken = true;
|
|
||||||
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
|
||||||
if (!isValuePosition)
|
|
||||||
{
|
|
||||||
//If we're about to write an end object/array, we shouldn't have a comma
|
|
||||||
if (reader.TokenType != JsonToken.EndArray && reader.TokenType != JsonToken.EndObject
|
|
||||||
&& isTerminalValue)
|
|
||||||
{
|
|
||||||
result.Append(",".SetColor(config.CommaColor));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isFirstToken)
|
|
||||||
{
|
|
||||||
result.AppendLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isFirstToken = false;
|
|
||||||
|
|
||||||
if (!isValuePosition)
|
|
||||||
{
|
|
||||||
result.Append("".PadLeft(reader.Depth * config.IndentSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
isTerminalValue = false;
|
|
||||||
isValuePosition = false;
|
|
||||||
JsonToken type = reader.TokenType;
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case JsonToken.StartObject:
|
|
||||||
result.Append("{".SetColor(config.ObjectBraceColor));
|
|
||||||
break;
|
|
||||||
case JsonToken.EndObject:
|
|
||||||
result.Append("}".SetColor(config.ObjectBraceColor));
|
|
||||||
isTerminalValue = true;
|
|
||||||
break;
|
|
||||||
case JsonToken.StartArray:
|
|
||||||
result.Append("[".SetColor(config.ArrayBraceColor));
|
|
||||||
break;
|
|
||||||
case JsonToken.EndArray:
|
|
||||||
result.Append("]".SetColor(config.ArrayBraceColor));
|
|
||||||
isTerminalValue = true;
|
|
||||||
break;
|
|
||||||
case JsonToken.PropertyName:
|
|
||||||
result.Append((reader.QuoteChar.ToString() + reader.Value + reader.QuoteChar).SetColor(config.NameColor) + ": ".SetColor(config.NameSeparatorColor));
|
|
||||||
isValuePosition = true;
|
|
||||||
break;
|
|
||||||
case JsonToken.Boolean:
|
|
||||||
result.Append(reader.Value.ToString().ToLowerInvariant().SetColor(config.BoolColor));
|
|
||||||
isTerminalValue = true;
|
|
||||||
break;
|
|
||||||
case JsonToken.Integer:
|
|
||||||
case JsonToken.Float:
|
|
||||||
result.Append(reader.Value.ToString().ToLowerInvariant().SetColor(config.NumericColor));
|
|
||||||
isTerminalValue = true;
|
|
||||||
break;
|
|
||||||
case JsonToken.Null:
|
|
||||||
result.Append("null".SetColor(config.NullColor));
|
|
||||||
isTerminalValue = true;
|
|
||||||
break;
|
|
||||||
case JsonToken.Comment:
|
|
||||||
result.Append(("//" + reader.Value).SetColor(config.NumericColor));
|
|
||||||
break;
|
|
||||||
case JsonToken.String:
|
|
||||||
result.Append((reader.QuoteChar.ToString() + reader.Value + reader.QuoteChar.ToString()).SetColor(config.StringColor));
|
|
||||||
isTerminalValue = true;
|
|
||||||
break;
|
|
||||||
case JsonToken.Raw:
|
|
||||||
case JsonToken.Date:
|
|
||||||
case JsonToken.Bytes:
|
|
||||||
case JsonToken.Undefined:
|
|
||||||
case JsonToken.None:
|
|
||||||
result.Append(reader.Value.ToString().SetColor(config.DefaultColor));
|
|
||||||
isTerminalValue = true;
|
|
||||||
break;
|
|
||||||
case JsonToken.EndConstructor:
|
|
||||||
case JsonToken.StartConstructor:
|
|
||||||
default:
|
|
||||||
result.Append(reader.Value.ToString().SetColor(config.DefaultColor));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,380 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using Microsoft.HttpRepl.Diagnostics;
|
|
||||||
using Microsoft.HttpRepl.Preferences;
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl
|
|
||||||
{
|
|
||||||
public class HttpState
|
|
||||||
{
|
|
||||||
private string _userProfileDir;
|
|
||||||
private string _prefsFilePath;
|
|
||||||
|
|
||||||
public HttpClient Client { get; }
|
|
||||||
|
|
||||||
public AllowedColors ErrorColor => this.GetColorPreference(WellKnownPreference.ErrorColor, AllowedColors.BoldRed);
|
|
||||||
|
|
||||||
public AllowedColors WarningColor => this.GetColorPreference(WellKnownPreference.WarningColor, AllowedColors.BoldYellow);
|
|
||||||
|
|
||||||
public Stack<string> PathSections { get; }
|
|
||||||
|
|
||||||
public IDirectoryStructure SwaggerStructure { get; set; }
|
|
||||||
|
|
||||||
public IDirectoryStructure Structure => DiagnosticsState.DiagEndpointsStructure == null
|
|
||||||
? SwaggerStructure
|
|
||||||
: SwaggerStructure == null
|
|
||||||
? DiagnosticsState.DiagEndpointsStructure
|
|
||||||
: new AggregateDirectoryStructure(SwaggerStructure, DiagnosticsState.DiagEndpointsStructure);
|
|
||||||
|
|
||||||
public Uri BaseAddress { get; set; }
|
|
||||||
|
|
||||||
public bool EchoRequest { get; set; }
|
|
||||||
|
|
||||||
public Dictionary<string, string> Preferences { get; }
|
|
||||||
|
|
||||||
public IReadOnlyDictionary<string, string> DefaultPreferences { get; }
|
|
||||||
|
|
||||||
public string UserProfileDir
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_userProfileDir == null)
|
|
||||||
{
|
|
||||||
bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
|
||||||
|
|
||||||
string profileDir = Environment.GetEnvironmentVariable(isWindows
|
|
||||||
? "USERPROFILE"
|
|
||||||
: "HOME");
|
|
||||||
|
|
||||||
_userProfileDir = profileDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _userProfileDir;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string PrefsFilePath => _prefsFilePath ?? (_prefsFilePath = Path.Combine(UserProfileDir, ".httpreplprefs"));
|
|
||||||
|
|
||||||
public Dictionary<string, IEnumerable<string>> Headers { get; }
|
|
||||||
|
|
||||||
public DiagnosticsState DiagnosticsState { get; }
|
|
||||||
|
|
||||||
public Uri SwaggerEndpoint { get; set; }
|
|
||||||
|
|
||||||
public HttpState()
|
|
||||||
{
|
|
||||||
Client = new HttpClient();
|
|
||||||
PathSections = new Stack<string>();
|
|
||||||
Preferences = new Dictionary<string, string>();
|
|
||||||
DefaultPreferences = CreateDefaultPreferencs();
|
|
||||||
Headers = new Dictionary<string, IEnumerable<string>>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
{ "User-Agent", new[] { "HTTP-REPL" } }
|
|
||||||
};
|
|
||||||
Preferences = new Dictionary<string, string>(DefaultPreferences);
|
|
||||||
LoadPreferences();
|
|
||||||
DiagnosticsState = new DiagnosticsState();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetPrompt()
|
|
||||||
{
|
|
||||||
return $"{GetEffectivePath(new string[0], false, out int _)?.ToString() ?? "(Disconnected)"}~ ";
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadPreferences()
|
|
||||||
{
|
|
||||||
if (File.Exists(PrefsFilePath))
|
|
||||||
{
|
|
||||||
string[] prefsFile = File.ReadAllLines(PrefsFilePath);
|
|
||||||
|
|
||||||
foreach (string line in prefsFile)
|
|
||||||
{
|
|
||||||
int equalsIndex = line.IndexOf('=');
|
|
||||||
|
|
||||||
if (equalsIndex < 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Preferences[line.Substring(0, equalsIndex)] = line.Substring(equalsIndex + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IReadOnlyDictionary<string, string> CreateDefaultPreferencs()
|
|
||||||
{
|
|
||||||
return new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
{ WellKnownPreference.ProtocolColor, "BoldGreen" },
|
|
||||||
{ WellKnownPreference.StatusColor, "BoldYellow" },
|
|
||||||
|
|
||||||
{ WellKnownPreference.JsonArrayBraceColor, "BoldCyan" },
|
|
||||||
{ WellKnownPreference.JsonCommaColor, "BoldYellow" },
|
|
||||||
{ WellKnownPreference.JsonNameColor, "BoldMagenta" },
|
|
||||||
{ WellKnownPreference.JsonNameSeparatorColor, "BoldWhite" },
|
|
||||||
{ WellKnownPreference.JsonObjectBraceColor, "Cyan" },
|
|
||||||
{ WellKnownPreference.JsonColor, "Green" }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SavePreferences()
|
|
||||||
{
|
|
||||||
List<string> lines = new List<string>();
|
|
||||||
foreach (KeyValuePair<string, string> entry in Preferences.OrderBy(x => x.Key))
|
|
||||||
{
|
|
||||||
//If the value didn't exist in the defaults or the value's different, include it in the user's preferences file
|
|
||||||
if (!DefaultPreferences.TryGetValue(entry.Key, out string value) || !string.Equals(value, entry.Value, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
lines.Add($"{entry.Key}={entry.Value}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File.WriteAllLines(PrefsFilePath, lines);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetExampleBody(string path, ref string contentType, string method)
|
|
||||||
{
|
|
||||||
Uri effectivePath = GetEffectivePath(path);
|
|
||||||
string rootRelativePath = effectivePath.LocalPath.Substring(BaseAddress.LocalPath.Length).TrimStart('/');
|
|
||||||
IDirectoryStructure structure = SwaggerStructure?.TraverseTo(rootRelativePath);
|
|
||||||
return structure?.RequestInfo?.GetRequestBodyForContentType(ref contentType, method);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> GetApplicableContentTypes(string method, string path)
|
|
||||||
{
|
|
||||||
Uri effectivePath = GetEffectivePath(path);
|
|
||||||
string rootRelativePath = effectivePath.LocalPath.Substring(BaseAddress.LocalPath.Length).TrimStart('/');
|
|
||||||
IDirectoryStructure structure = SwaggerStructure?.TraverseTo(rootRelativePath);
|
|
||||||
IReadOnlyDictionary<string, IReadOnlyList<string>> contentTypesByMethod = structure?.RequestInfo?.ContentTypesByMethod;
|
|
||||||
|
|
||||||
if (contentTypesByMethod != null)
|
|
||||||
{
|
|
||||||
if (method is null)
|
|
||||||
{
|
|
||||||
return contentTypesByMethod.Values.SelectMany(x => x).Distinct(StringComparer.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contentTypesByMethod.TryGetValue(method, out IReadOnlyList<string> contentTypes))
|
|
||||||
{
|
|
||||||
return contentTypes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Uri GetEffectivePath(string commandSpecifiedPath)
|
|
||||||
{
|
|
||||||
if (Uri.TryCreate(commandSpecifiedPath, UriKind.Absolute, out Uri absoluteUri))
|
|
||||||
{
|
|
||||||
return absoluteUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
UriBuilder builder = new UriBuilder(BaseAddress);
|
|
||||||
string path = string.Join('/', PathSections.Reverse());
|
|
||||||
string[] parts = path.Split('?');
|
|
||||||
string query = null;
|
|
||||||
string query2 = null;
|
|
||||||
|
|
||||||
if (parts.Length > 1)
|
|
||||||
{
|
|
||||||
path = parts[0];
|
|
||||||
query = string.Join('?', parts.Skip(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Path += path;
|
|
||||||
|
|
||||||
if (commandSpecifiedPath.Length > 0)
|
|
||||||
{
|
|
||||||
if (commandSpecifiedPath[0] != '/')
|
|
||||||
{
|
|
||||||
string argPath = commandSpecifiedPath;
|
|
||||||
if (builder.Path.Length > 0 && builder.Path[builder.Path.Length - 1] != '/')
|
|
||||||
{
|
|
||||||
argPath = "/" + argPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
int queryIndex = argPath.IndexOf('?');
|
|
||||||
path = argPath;
|
|
||||||
|
|
||||||
if (queryIndex > -1)
|
|
||||||
{
|
|
||||||
query2 = argPath.Substring(queryIndex + 1);
|
|
||||||
path = argPath.Substring(0, queryIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Path += path;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int queryIndex = commandSpecifiedPath.IndexOf('?');
|
|
||||||
path = commandSpecifiedPath;
|
|
||||||
|
|
||||||
if (queryIndex > -1)
|
|
||||||
{
|
|
||||||
query2 = commandSpecifiedPath.Substring(queryIndex + 1);
|
|
||||||
path = commandSpecifiedPath.Substring(0, queryIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Path = path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
int queryIndex = commandSpecifiedPath.IndexOf('?');
|
|
||||||
path = commandSpecifiedPath;
|
|
||||||
|
|
||||||
if (queryIndex > -1)
|
|
||||||
{
|
|
||||||
query2 = commandSpecifiedPath.Substring(queryIndex + 1);
|
|
||||||
path = commandSpecifiedPath.Substring(0, queryIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Path += path;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query != null)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(builder.Query))
|
|
||||||
{
|
|
||||||
query = "&" + query;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Query += query;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query2 != null)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(builder.Query))
|
|
||||||
{
|
|
||||||
query2 = "&" + query2;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Query += query2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.Uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Uri GetEffectivePath(IReadOnlyList<string> sections, bool requiresBody, out int filePathIndex)
|
|
||||||
{
|
|
||||||
filePathIndex = 1;
|
|
||||||
|
|
||||||
if (BaseAddress == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
UriBuilder builder = new UriBuilder(BaseAddress);
|
|
||||||
string path = string.Join('/', PathSections.Reverse());
|
|
||||||
string[] parts = path.Split('?');
|
|
||||||
string query = null;
|
|
||||||
string query2 = null;
|
|
||||||
|
|
||||||
if (parts.Length > 1)
|
|
||||||
{
|
|
||||||
path = parts[0];
|
|
||||||
query = string.Join('?', parts.Skip(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Path += path;
|
|
||||||
|
|
||||||
if (sections.Count > 1)
|
|
||||||
{
|
|
||||||
if (!requiresBody || !File.Exists(sections[1]))
|
|
||||||
{
|
|
||||||
if (sections[1].Length > 0)
|
|
||||||
{
|
|
||||||
if (sections[1][0] != '/')
|
|
||||||
{
|
|
||||||
string argPath = sections[1];
|
|
||||||
if (builder.Path.Length > 0 && builder.Path[builder.Path.Length - 1] != '/')
|
|
||||||
{
|
|
||||||
argPath = "/" + argPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
int queryIndex = argPath.IndexOf('?');
|
|
||||||
path = argPath;
|
|
||||||
|
|
||||||
if (queryIndex > -1)
|
|
||||||
{
|
|
||||||
query2 = argPath.Substring(queryIndex + 1);
|
|
||||||
path = argPath.Substring(0, queryIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Path += path;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int queryIndex = sections[1].IndexOf('?');
|
|
||||||
path = sections[1];
|
|
||||||
|
|
||||||
if (queryIndex > -1)
|
|
||||||
{
|
|
||||||
query2 = sections[1].Substring(queryIndex + 1);
|
|
||||||
path = sections[1].Substring(0, queryIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Path = path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
int queryIndex = sections[1].IndexOf('?');
|
|
||||||
path = sections[1];
|
|
||||||
|
|
||||||
if (queryIndex > -1)
|
|
||||||
{
|
|
||||||
query2 = sections[1].Substring(queryIndex + 1);
|
|
||||||
path = sections[1].Substring(0, queryIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Path += path;
|
|
||||||
}
|
|
||||||
|
|
||||||
filePathIndex = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query != null)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(builder.Query))
|
|
||||||
{
|
|
||||||
query = "&" + query;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Query += query;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query2 != null)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(builder.Query))
|
|
||||||
{
|
|
||||||
query2 = "&" + query2;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Query += query2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.Uri;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl
|
|
||||||
{
|
|
||||||
public interface IDirectoryStructure
|
|
||||||
{
|
|
||||||
IEnumerable<string> DirectoryNames { get; }
|
|
||||||
|
|
||||||
IDirectoryStructure Parent { get; }
|
|
||||||
|
|
||||||
IDirectoryStructure GetChildDirectory(string name);
|
|
||||||
|
|
||||||
IRequestInfo RequestInfo { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl
|
|
||||||
{
|
|
||||||
public interface IRequestInfo
|
|
||||||
{
|
|
||||||
IReadOnlyDictionary<string, IReadOnlyList<string>> ContentTypesByMethod { get; }
|
|
||||||
|
|
||||||
IReadOnlyList<string> Methods { get; }
|
|
||||||
|
|
||||||
string GetRequestBodyForContentType(ref string contentType, string method);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
|
||||||
<PackAsTool>true</PackAsTool>
|
|
||||||
<AssemblyName>dotnet-httprepl</AssemblyName>
|
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<Description>Command line tool to for making HTTP calls and viewing their results.</Description>
|
|
||||||
<PackageTags>dotnet;http;httprepl</PackageTags>
|
|
||||||
<!-- This is a requirement for Microsoft tool packages only. -->
|
|
||||||
<PackAsToolShimRuntimeIdentifiers>win-x64;win-x86</PackAsToolShimRuntimeIdentifiers>
|
|
||||||
|
|
||||||
<!-- Temporarily disables producing this project as a package while we work through some RTM-blocking bugs. -->
|
|
||||||
<IsPackable>false</IsPackable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="$(MicrosoftWebApiClientPackageVersion)" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Microsoft.Repl\Microsoft.Repl.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<SignedPackageFile Include="$(PublishDir)Microsoft.Repl.dll" PackagePath="tools/$(TargetFramework)/any/Microsoft.Repl.dll" Certificate="$(AssemblySigningCertName)" />
|
|
||||||
<SignedPackageFile Include="$(PublishDir)Newtonsoft.Json.dll" PackagePath="tools/$(TargetFramework)/any/Newtonsoft.Json.dll" Certificate="$(AssemblySigning3rdPartyCertName)" />
|
|
||||||
<SignedPackageFile Include="$(PublishDir)Newtonsoft.Json.Bson.dll" PackagePath="tools/$(TargetFramework)/any/Newtonsoft.Json.Bson.dll" Certificate="$(AssemblySigning3rdPartyCertName)" />
|
|
||||||
<ExcludePackageFileFromSigning Include="$(PublishDir)System.Net.Http.Formatting.dll" PackagePath="tools/$(TargetFramework)/any/System.Net.Http.Formatting.dll" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.OpenApi
|
|
||||||
{
|
|
||||||
public class Either<TOption1, TOption2>
|
|
||||||
{
|
|
||||||
public Either(TOption1 option1)
|
|
||||||
{
|
|
||||||
Option1 = option1;
|
|
||||||
IsOption1 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Either(TOption2 option2)
|
|
||||||
{
|
|
||||||
Option2 = option2;
|
|
||||||
IsOption1 = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsOption1 { get; }
|
|
||||||
|
|
||||||
public TOption1 Option1 { get; }
|
|
||||||
|
|
||||||
public TOption2 Option2 { get; }
|
|
||||||
|
|
||||||
public static implicit operator Either<TOption1, TOption2>(TOption1 value)
|
|
||||||
{
|
|
||||||
return new Either<TOption1, TOption2>(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static implicit operator Either<TOption1, TOption2>(TOption2 value)
|
|
||||||
{
|
|
||||||
return new Either<TOption1, TOption2>(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.OpenApi
|
|
||||||
{
|
|
||||||
public class EitherConverter<TOption1, TOption2> : JsonConverter
|
|
||||||
{
|
|
||||||
public override bool CanConvert(Type objectType)
|
|
||||||
{
|
|
||||||
return typeof(TOption1).IsAssignableFrom(objectType) || typeof(TOption2).IsAssignableFrom(objectType) || typeof(EitherConverter<TOption1, TOption2>) == objectType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
TOption1 option1 = serializer.Deserialize<TOption1>(reader);
|
|
||||||
return new Either<TOption1, TOption2>(option1);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
TOption2 option2 = serializer.Deserialize<TOption2>(reader);
|
|
||||||
return new Either<TOption1, TOption2>(option2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.OpenApi
|
|
||||||
{
|
|
||||||
public class EndpointMetadata
|
|
||||||
{
|
|
||||||
public EndpointMetadata(string path, IReadOnlyDictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>> requestsByMethodAndContentType)
|
|
||||||
{
|
|
||||||
Path = path;
|
|
||||||
AvailableRequests = requestsByMethodAndContentType ?? new Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Path { get; }
|
|
||||||
|
|
||||||
public IReadOnlyDictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>> AvailableRequests { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.OpenApi
|
|
||||||
{
|
|
||||||
public class EndpointMetadataReader
|
|
||||||
{
|
|
||||||
private readonly List<IEndpointMetadataReader> _readers = new List<IEndpointMetadataReader>
|
|
||||||
{
|
|
||||||
new OpenApiV3EndpointMetadataReader(),
|
|
||||||
new SwaggerV2EndpointMetadataReader(),
|
|
||||||
new SwaggerV1EndpointMetadataReader()
|
|
||||||
};
|
|
||||||
|
|
||||||
public void RegisterReader(IEndpointMetadataReader reader)
|
|
||||||
{
|
|
||||||
_readers.Add(reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<EndpointMetadata> Read(JObject document)
|
|
||||||
{
|
|
||||||
foreach (IEndpointMetadataReader reader in _readers)
|
|
||||||
{
|
|
||||||
if (reader.CanHandle(document))
|
|
||||||
{
|
|
||||||
IEnumerable<EndpointMetadata> result = reader.ReadMetadata(document);
|
|
||||||
|
|
||||||
if (result != null)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.OpenApi
|
|
||||||
{
|
|
||||||
public interface IEndpointMetadataReader
|
|
||||||
{
|
|
||||||
bool CanHandle(JObject document);
|
|
||||||
|
|
||||||
IEnumerable<EndpointMetadata> ReadMetadata(JObject document);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.OpenApi
|
|
||||||
{
|
|
||||||
public class OpenApiV3EndpointMetadataReader : IEndpointMetadataReader
|
|
||||||
{
|
|
||||||
public bool CanHandle(JObject document)
|
|
||||||
{
|
|
||||||
return (document["openapi"]?.ToString() ?? "").StartsWith("3.", StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<EndpointMetadata> ReadMetadata(JObject document)
|
|
||||||
{
|
|
||||||
List<EndpointMetadata> metadata = new List<EndpointMetadata>();
|
|
||||||
|
|
||||||
if (document["paths"] is JObject paths)
|
|
||||||
{
|
|
||||||
foreach (JProperty path in paths.Properties())
|
|
||||||
{
|
|
||||||
if (!(path.Value is JObject pathBody))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>> requestMethods = new Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
foreach (JProperty method in pathBody.Properties())
|
|
||||||
{
|
|
||||||
List<Parameter> parameters = new List<Parameter>();
|
|
||||||
|
|
||||||
if (method.Value is JObject methodBody)
|
|
||||||
{
|
|
||||||
if (methodBody["parameters"] is JArray parametersArray)
|
|
||||||
{
|
|
||||||
foreach (JObject parameterObj in parametersArray.OfType<JObject>())
|
|
||||||
{
|
|
||||||
Parameter p = parameterObj.ToObject<Parameter>();
|
|
||||||
p.Location = parameterObj["in"]?.ToString();
|
|
||||||
|
|
||||||
if (!(parameterObj["schema"] is JObject schemaObject))
|
|
||||||
{
|
|
||||||
schemaObject = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Schema = schemaObject?.ToObject<Schema>() ?? parameterObj.ToObject<Schema>();
|
|
||||||
parameters.Add(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (methodBody["requestBody"] is JObject bodyObject)
|
|
||||||
{
|
|
||||||
if (!(bodyObject["content"] is JObject contentTypeLookup))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (JProperty contentTypeEntry in contentTypeLookup.Properties())
|
|
||||||
{
|
|
||||||
List<Parameter> parametersByContentType = new List<Parameter>(parameters);
|
|
||||||
Parameter p = bodyObject.ToObject<Parameter>();
|
|
||||||
p.Location = "body";
|
|
||||||
p.IsRequired = bodyObject["required"]?.ToObject<bool>() ?? false;
|
|
||||||
|
|
||||||
if (!(bodyObject["schema"] is JObject schemaObject))
|
|
||||||
{
|
|
||||||
schemaObject = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Schema = schemaObject?.ToObject<Schema>() ?? bodyObject.ToObject<Schema>();
|
|
||||||
parametersByContentType.Add(p);
|
|
||||||
|
|
||||||
Dictionary<string, IReadOnlyList<Parameter>> bucketByMethod;
|
|
||||||
if (!requestMethods.TryGetValue(method.Name, out IReadOnlyDictionary<string, IReadOnlyList<Parameter>> bucketByMethodRaw))
|
|
||||||
{
|
|
||||||
requestMethods[method.Name] = bucketByMethodRaw = new Dictionary<string, IReadOnlyList<Parameter>>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
{ "", parametersByContentType }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
bucketByMethod = (Dictionary<string, IReadOnlyList<Parameter>>)bucketByMethodRaw;
|
|
||||||
bucketByMethod[contentTypeEntry.Name] = parametersByContentType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
metadata.Add(new EndpointMetadata(path.Name, requestMethods));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return metadata;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.OpenApi
|
|
||||||
{
|
|
||||||
public class Parameter
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
public string Location { get; set; }
|
|
||||||
|
|
||||||
public bool IsRequired { get; set; }
|
|
||||||
|
|
||||||
public Schema Schema { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,150 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.OpenApi
|
|
||||||
{
|
|
||||||
public static class PointerUtil
|
|
||||||
{
|
|
||||||
public static Task<JToken> ResolvePointersAsync(Uri loadLocation, JToken root, HttpClient client)
|
|
||||||
{
|
|
||||||
return ResolvePointersAsync(loadLocation, root, root, client);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<JToken> ResolvePointersAsync(Uri loadLocation, JToken root, JToken toResolve, HttpClient client)
|
|
||||||
{
|
|
||||||
JToken cursor = root;
|
|
||||||
|
|
||||||
if (toResolve is JArray arr)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < arr.Count; ++i)
|
|
||||||
{
|
|
||||||
arr[i] = await ResolvePointersAsync(loadLocation, root, arr[i], client).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (toResolve is JObject obj)
|
|
||||||
{
|
|
||||||
if (obj["$ref"] is JValue refVal && refVal.Type == JTokenType.String)
|
|
||||||
{
|
|
||||||
if (!Uri.TryCreate((string)refVal.Value, UriKind.RelativeOrAbsolute, out Uri loadTarget))
|
|
||||||
{
|
|
||||||
//TODO: Error resolving pointer (pointer must be a valid URI)
|
|
||||||
return new JValue((object)null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!loadTarget.IsAbsoluteUri)
|
|
||||||
{
|
|
||||||
if (!Uri.TryCreate(loadLocation, loadTarget, out loadTarget))
|
|
||||||
{
|
|
||||||
//TODO: Error resolving pointer (could not combine with base path)
|
|
||||||
return new JValue((object)null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check to see if we're changing source documents, if we are, get it
|
|
||||||
if (!string.Equals(loadLocation.Host, loadTarget.Host, StringComparison.OrdinalIgnoreCase) || !string.Equals(loadLocation.AbsolutePath, loadTarget.AbsolutePath, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
HttpResponseMessage responseMessage = await client.GetAsync(loadTarget).ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (!responseMessage.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
//TODO: Error resolving pointer (could not get referenced document)
|
|
||||||
return new JValue((object)null);
|
|
||||||
}
|
|
||||||
|
|
||||||
string responseString = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
|
|
||||||
JToken newRoot;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
newRoot = JToken.Parse(responseString);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
//TODO: Error resolving pointer (referenced document is not valid JSON)
|
|
||||||
return new JValue((object)null);
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor = await ResolvePointersAsync(loadTarget, newRoot, newRoot, client).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
//We're in the right document, grab the bookmark (fragment) of the URI and get the element at that path
|
|
||||||
string fragment = loadTarget.Fragment;
|
|
||||||
|
|
||||||
if (fragment.StartsWith('#'))
|
|
||||||
{
|
|
||||||
fragment = fragment.Substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
string[] parts = fragment.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
|
|
||||||
for (int i = 0; i < parts.Length; ++i)
|
|
||||||
{
|
|
||||||
if (cursor is JArray ca)
|
|
||||||
{
|
|
||||||
if (!int.TryParse(parts[i], NumberStyles.Integer, CultureInfo.InvariantCulture, out int index))
|
|
||||||
{
|
|
||||||
//TODO: Error resolving pointer, array index is non-integral
|
|
||||||
return new JValue((object)null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index < 0 || index >= ca.Count)
|
|
||||||
{
|
|
||||||
//TODO: Error resolving pointer, array index is out of bounds
|
|
||||||
return new JValue((object)null);
|
|
||||||
}
|
|
||||||
|
|
||||||
JToken val = ca[index];
|
|
||||||
if (val is JObject vo && vo.TryGetValue("$ref", out JToken vor) && vor is JValue vorv && vorv.Type == JTokenType.String)
|
|
||||||
{
|
|
||||||
cursor = await ResolvePointersAsync(loadLocation, root, val, client).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cursor = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (cursor is JObject co)
|
|
||||||
{
|
|
||||||
if (!co.TryGetValue(parts[i], out JToken val))
|
|
||||||
{
|
|
||||||
//TODO: Error resolving pointer, no such property on object
|
|
||||||
return new JValue((object)null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (val is JObject vo && vo.TryGetValue("$ref", out JToken vor) && vor is JValue vorv && vorv.Type == JTokenType.String)
|
|
||||||
{
|
|
||||||
cursor = await ResolvePointersAsync(loadLocation, root, val, client).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cursor = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//TODO: Error resolving pointer, cannot index into literal
|
|
||||||
return new JValue((object)null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor = await ResolvePointersAsync(loadLocation, root, cursor, client);
|
|
||||||
return cursor.DeepClone();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (JProperty property in obj.Properties().ToList())
|
|
||||||
{
|
|
||||||
obj[property.Name] = await ResolvePointersAsync(loadLocation, root, property.Value, client).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return toResolve;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.OpenApi
|
|
||||||
{
|
|
||||||
public class Schema
|
|
||||||
{
|
|
||||||
public void PrepareForUsage(JToken document)
|
|
||||||
{
|
|
||||||
AdditionalProperties?.Option1?.PrepareForUsage(document);
|
|
||||||
|
|
||||||
if (AllOf != null)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < AllOf.Length; ++i)
|
|
||||||
{
|
|
||||||
AllOf[i].PrepareForUsage(document);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AnyOf != null)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < AnyOf.Length; ++i)
|
|
||||||
{
|
|
||||||
AnyOf[i].PrepareForUsage(document);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OneOf != null)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < OneOf.Length; ++i)
|
|
||||||
{
|
|
||||||
OneOf[i].PrepareForUsage(document);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Properties != null)
|
|
||||||
{
|
|
||||||
IReadOnlyList<string> keys = Properties.Keys.ToList();
|
|
||||||
for (int i = 0; i < keys.Count; ++i)
|
|
||||||
{
|
|
||||||
Properties[keys[i]]?.PrepareForUsage(document);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Items?.PrepareForUsage(document);
|
|
||||||
Not?.PrepareForUsage(document);
|
|
||||||
|
|
||||||
if (Required?.Option1 != null)
|
|
||||||
{
|
|
||||||
if (Properties != null)
|
|
||||||
{
|
|
||||||
foreach (string propertyName in Required.Option1)
|
|
||||||
{
|
|
||||||
if (Properties.TryGetValue(propertyName, out Schema value))
|
|
||||||
{
|
|
||||||
value.Required = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Required = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonConverter(typeof(EitherConverter<Schema, bool>))]
|
|
||||||
public Either<Schema, bool> AdditionalProperties { get; set; }
|
|
||||||
|
|
||||||
public Schema[] AllOf { get; set; }
|
|
||||||
|
|
||||||
public Schema[] AnyOf { get; set; }
|
|
||||||
|
|
||||||
public object Default { get; set; }
|
|
||||||
|
|
||||||
public string Description { get; set; }
|
|
||||||
|
|
||||||
public object[] Enum { get; set; }
|
|
||||||
|
|
||||||
public object Example { get; set; }
|
|
||||||
|
|
||||||
public bool ExclusiveMaximum { get; set; }
|
|
||||||
|
|
||||||
public bool ExclusiveMinimum { get; set; }
|
|
||||||
|
|
||||||
public string Format { get; set; }
|
|
||||||
|
|
||||||
public Schema Items { get; set; }
|
|
||||||
|
|
||||||
public double? Maximum { get; set; }
|
|
||||||
|
|
||||||
public double? Minimum { get; set; }
|
|
||||||
|
|
||||||
public int? MaxItems { get; set; }
|
|
||||||
|
|
||||||
public int? MinItems { get; set; }
|
|
||||||
|
|
||||||
public int? MaxLength { get; set; }
|
|
||||||
|
|
||||||
public int? MinLength { get; set; }
|
|
||||||
|
|
||||||
public int? MaxProperties { get; set; }
|
|
||||||
|
|
||||||
public int? MinProperties { get; set; }
|
|
||||||
|
|
||||||
public double? MultipleOf { get; set; }
|
|
||||||
|
|
||||||
public Schema Not { get; set; }
|
|
||||||
|
|
||||||
public Schema[] OneOf { get; set; }
|
|
||||||
|
|
||||||
public string Pattern { get; set; }
|
|
||||||
|
|
||||||
public Dictionary<string, Schema> Properties { get; set; }
|
|
||||||
|
|
||||||
[JsonConverter(typeof(EitherConverter<string[], bool>))]
|
|
||||||
public Either<string[], bool> Required { get; set; }
|
|
||||||
|
|
||||||
public string Title { get; set; }
|
|
||||||
|
|
||||||
public string Type { get; set; }
|
|
||||||
|
|
||||||
public bool UniqueItems { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,109 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.OpenApi
|
|
||||||
{
|
|
||||||
public class SwaggerV1EndpointMetadataReader : IEndpointMetadataReader
|
|
||||||
{
|
|
||||||
public bool CanHandle(JObject document)
|
|
||||||
{
|
|
||||||
return (document["swaggerVersion"]?.ToString() ?? "").StartsWith("1.", StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<EndpointMetadata> ReadMetadata(JObject document)
|
|
||||||
{
|
|
||||||
List<EndpointMetadata> metadata = new List<EndpointMetadata>();
|
|
||||||
|
|
||||||
if (!(document["consumes"] is JArray globalConsumes))
|
|
||||||
{
|
|
||||||
globalConsumes = new JArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (document["apis"] is JObject obj)
|
|
||||||
{
|
|
||||||
foreach (JProperty property in obj.Properties())
|
|
||||||
{
|
|
||||||
string path = obj["path"]?.ToString();
|
|
||||||
|
|
||||||
if (path is null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>> requestMethods = new Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>>(StringComparer.Ordinal);
|
|
||||||
|
|
||||||
if (obj["operations"] is JArray operations)
|
|
||||||
{
|
|
||||||
foreach (JObject operationObject in operations.OfType<JObject>())
|
|
||||||
{
|
|
||||||
string method = operationObject["method"]?.ToString();
|
|
||||||
List<Parameter> parameters = new List<Parameter>();
|
|
||||||
|
|
||||||
if (operationObject["parameters"] is JArray parametersArray)
|
|
||||||
{
|
|
||||||
foreach (JObject parameterObj in parametersArray.OfType<JObject>())
|
|
||||||
{
|
|
||||||
Parameter p = parameterObj.ToObject<Parameter>();
|
|
||||||
p.Location = parameterObj["paramType"]?.ToString();
|
|
||||||
p.IsRequired = parameterObj["required"]?.ToObject<bool>() ?? false;
|
|
||||||
|
|
||||||
string type = parameterObj["type"]?.ToString();
|
|
||||||
|
|
||||||
if (type is null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type.ToUpperInvariant())
|
|
||||||
{
|
|
||||||
case "INTEGER":
|
|
||||||
case "NUMBER":
|
|
||||||
case "STRING":
|
|
||||||
case "BOOLEAN":
|
|
||||||
p.Schema = new Schema { Type = type };
|
|
||||||
break;
|
|
||||||
case "FILE":
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (document["models"]?[type] is JObject schemaObject)
|
|
||||||
{
|
|
||||||
//TODO: Handle subtypes (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/1.2.md#527-model-object)
|
|
||||||
p.Schema = schemaObject.ToObject<Schema>();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
parameters.Add(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(operationObject["consumes"] is JArray consumes))
|
|
||||||
{
|
|
||||||
consumes = globalConsumes;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary<string, IReadOnlyList<Parameter>> parametersByContentType = new Dictionary<string, IReadOnlyList<Parameter>>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
{ "", parameters }
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (JValue value in consumes.OfType<JValue>().Where(x => x.Type == JTokenType.String))
|
|
||||||
{
|
|
||||||
parametersByContentType[value.ToString()] = parameters;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
metadata.Add(new EndpointMetadata(path, requestMethods));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return metadata;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.OpenApi
|
|
||||||
{
|
|
||||||
public class SwaggerV2EndpointMetadataReader : IEndpointMetadataReader
|
|
||||||
{
|
|
||||||
public bool CanHandle(JObject document)
|
|
||||||
{
|
|
||||||
return (document["swagger"]?.ToString() ?? "").StartsWith("2.", StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<EndpointMetadata> ReadMetadata(JObject document)
|
|
||||||
{
|
|
||||||
List<EndpointMetadata> metadata = new List<EndpointMetadata>();
|
|
||||||
|
|
||||||
if (!(document["consumes"] is JArray globalConsumes))
|
|
||||||
{
|
|
||||||
globalConsumes = new JArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (document["paths"] is JObject obj)
|
|
||||||
{
|
|
||||||
foreach (JProperty property in obj.Properties())
|
|
||||||
{
|
|
||||||
if (!(property.Value is JObject requestMethodInfos))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>> requestMethods = new Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<Parameter>>>(StringComparer.Ordinal);
|
|
||||||
|
|
||||||
foreach (JProperty methodInfo in requestMethodInfos.Properties())
|
|
||||||
{
|
|
||||||
List<Parameter> parameters = new List<Parameter>();
|
|
||||||
|
|
||||||
if (methodInfo.Value is JObject methodInfoDescription)
|
|
||||||
{
|
|
||||||
if (methodInfoDescription["parameters"] is JArray parametersArray)
|
|
||||||
{
|
|
||||||
foreach (JObject parameterObj in parametersArray.OfType<JObject>())
|
|
||||||
{
|
|
||||||
//TODO: Resolve refs here
|
|
||||||
|
|
||||||
Parameter p = parameterObj.ToObject<Parameter>();
|
|
||||||
p.Location = parameterObj["in"]?.ToString();
|
|
||||||
p.IsRequired = parameterObj["required"]?.ToObject<bool>() ?? false;
|
|
||||||
|
|
||||||
if (!(parameterObj["schema"] is JObject schemaObject))
|
|
||||||
{
|
|
||||||
schemaObject = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Schema = schemaObject?.ToObject<Schema>() ?? parameterObj.ToObject<Schema>();
|
|
||||||
parameters.Add(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(methodInfoDescription["consumes"] is JArray consumes))
|
|
||||||
{
|
|
||||||
consumes = globalConsumes;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary<string, IReadOnlyList<Parameter>> parametersByContentType = new Dictionary<string, IReadOnlyList<Parameter>>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
{ "", parameters }
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (JValue value in consumes.OfType<JValue>().Where(x => x.Type == JTokenType.String))
|
|
||||||
{
|
|
||||||
parametersByContentType[value.ToString()] = parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
requestMethods[methodInfo.Name] = parametersByContentType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
metadata.Add(new EndpointMetadata(property.Name, requestMethods));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return metadata;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Preferences
|
|
||||||
{
|
|
||||||
public interface IJsonConfig
|
|
||||||
{
|
|
||||||
int IndentSize { get; }
|
|
||||||
|
|
||||||
AllowedColors DefaultColor { get; }
|
|
||||||
|
|
||||||
AllowedColors ArrayBraceColor { get; }
|
|
||||||
|
|
||||||
AllowedColors ObjectBraceColor { get; }
|
|
||||||
|
|
||||||
AllowedColors CommaColor { get; }
|
|
||||||
|
|
||||||
AllowedColors NameColor { get; }
|
|
||||||
|
|
||||||
AllowedColors NameSeparatorColor { get; }
|
|
||||||
|
|
||||||
AllowedColors BoolColor { get; }
|
|
||||||
|
|
||||||
AllowedColors NumericColor { get; }
|
|
||||||
|
|
||||||
AllowedColors StringColor { get; }
|
|
||||||
|
|
||||||
AllowedColors NullColor { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Preferences
|
|
||||||
{
|
|
||||||
public class JsonConfig : IJsonConfig
|
|
||||||
{
|
|
||||||
private readonly HttpState _state;
|
|
||||||
|
|
||||||
public int IndentSize => _state.GetIntPreference(WellKnownPreference.JsonIndentSize, 2);
|
|
||||||
|
|
||||||
public AllowedColors DefaultColor => _state.GetColorPreference(WellKnownPreference.JsonColor);
|
|
||||||
|
|
||||||
private AllowedColors DefaultBraceColor => _state.GetColorPreference(WellKnownPreference.JsonBraceColor, DefaultSyntaxColor);
|
|
||||||
|
|
||||||
private AllowedColors DefaultSyntaxColor => _state.GetColorPreference(WellKnownPreference.JsonSyntaxColor, DefaultColor);
|
|
||||||
|
|
||||||
private AllowedColors DefaultLiteralColor => _state.GetColorPreference(WellKnownPreference.JsonLiteralColor, DefaultColor);
|
|
||||||
|
|
||||||
public AllowedColors ArrayBraceColor => _state.GetColorPreference(WellKnownPreference.JsonArrayBraceColor, DefaultBraceColor);
|
|
||||||
|
|
||||||
public AllowedColors ObjectBraceColor => _state.GetColorPreference(WellKnownPreference.JsonObjectBraceColor, DefaultBraceColor);
|
|
||||||
|
|
||||||
public AllowedColors CommaColor => _state.GetColorPreference(WellKnownPreference.JsonCommaColor, DefaultSyntaxColor);
|
|
||||||
|
|
||||||
public AllowedColors NameColor => _state.GetColorPreference(WellKnownPreference.JsonNameColor, StringColor);
|
|
||||||
|
|
||||||
public AllowedColors NameSeparatorColor => _state.GetColorPreference(WellKnownPreference.JsonNameSeparatorColor, DefaultSyntaxColor);
|
|
||||||
|
|
||||||
public AllowedColors BoolColor => _state.GetColorPreference(WellKnownPreference.JsonBoolColor, DefaultLiteralColor);
|
|
||||||
|
|
||||||
public AllowedColors NumericColor => _state.GetColorPreference(WellKnownPreference.JsonNumericColor, DefaultLiteralColor);
|
|
||||||
|
|
||||||
public AllowedColors StringColor => _state.GetColorPreference(WellKnownPreference.JsonStringColor, DefaultLiteralColor);
|
|
||||||
|
|
||||||
public AllowedColors NullColor => _state.GetColorPreference(WellKnownPreference.JsonNullColor, DefaultLiteralColor);
|
|
||||||
|
|
||||||
public JsonConfig(HttpState state)
|
|
||||||
{
|
|
||||||
_state = state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Preferences
|
|
||||||
{
|
|
||||||
public class RequestConfig : RequestOrResponseConfig
|
|
||||||
{
|
|
||||||
public RequestConfig(HttpState state)
|
|
||||||
: base(state)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override AllowedColors BodyColor => State.GetColorPreference(WellKnownPreference.RequestBodyColor, base.BodyColor);
|
|
||||||
|
|
||||||
public override AllowedColors SchemeColor => State.GetColorPreference(WellKnownPreference.RequestSchemeColor, base.SchemeColor);
|
|
||||||
|
|
||||||
public override AllowedColors HeaderKeyColor => State.GetColorPreference(WellKnownPreference.RequestHeaderKeyColor, base.HeaderKeyColor);
|
|
||||||
|
|
||||||
public override AllowedColors HeaderSeparatorColor => State.GetColorPreference(WellKnownPreference.RequestHeaderSeparatorColor, base.HeaderSeparatorColor);
|
|
||||||
|
|
||||||
public override AllowedColors HeaderValueSeparatorColor => State.GetColorPreference(WellKnownPreference.RequestHeaderValueSeparatorColor, base.HeaderValueSeparatorColor);
|
|
||||||
|
|
||||||
public override AllowedColors HeaderValueColor => State.GetColorPreference(WellKnownPreference.RequestHeaderValueColor, base.HeaderValueColor);
|
|
||||||
|
|
||||||
public override AllowedColors HeaderColor => State.GetColorPreference(WellKnownPreference.RequestHeaderColor, base.HeaderColor);
|
|
||||||
|
|
||||||
public override AllowedColors GeneralColor => State.GetColorPreference(WellKnownPreference.RequestColor, base.GeneralColor);
|
|
||||||
|
|
||||||
public override AllowedColors ProtocolColor => State.GetColorPreference(WellKnownPreference.RequestProtocolColor, base.ProtocolColor);
|
|
||||||
|
|
||||||
public override AllowedColors ProtocolNameColor => State.GetColorPreference(WellKnownPreference.RequestProtocolNameColor, base.ProtocolNameColor);
|
|
||||||
|
|
||||||
public override AllowedColors ProtocolVersionColor => State.GetColorPreference(WellKnownPreference.RequestProtocolVersionColor, base.ProtocolVersionColor);
|
|
||||||
|
|
||||||
public override AllowedColors ProtocolSeparatorColor => State.GetColorPreference(WellKnownPreference.RequestProtocolSeparatorColor, base.ProtocolSeparatorColor);
|
|
||||||
|
|
||||||
public override AllowedColors StatusColor => State.GetColorPreference(WellKnownPreference.RequestStatusColor, base.StatusColor);
|
|
||||||
|
|
||||||
public override AllowedColors StatusCodeColor => State.GetColorPreference(WellKnownPreference.RequestStatusCodeColor, base.StatusCodeColor);
|
|
||||||
|
|
||||||
public override AllowedColors StatusReasonPhraseColor => State.GetColorPreference(WellKnownPreference.RequestStatusReaseonPhraseColor, base.StatusReasonPhraseColor);
|
|
||||||
|
|
||||||
public AllowedColors MethodColor => State.GetColorPreference(WellKnownPreference.RequestMethodColor, GeneralColor);
|
|
||||||
|
|
||||||
public AllowedColors AddressColor => State.GetColorPreference(WellKnownPreference.RequestAddressColor, GeneralColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using Microsoft.Repl.ConsoleHandling;
|
|
||||||
|
|
||||||
namespace Microsoft.HttpRepl.Preferences
|
|
||||||
{
|
|
||||||
public abstract class RequestOrResponseConfig
|
|
||||||
{
|
|
||||||
protected HttpState State { get; }
|
|
||||||
|
|
||||||
protected RequestOrResponseConfig(HttpState state)
|
|
||||||
{
|
|
||||||
State = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual AllowedColors BodyColor => State.GetColorPreference(WellKnownPreference.BodyColor, GeneralColor);
|
|
||||||
|
|
||||||
public virtual AllowedColors SchemeColor => State.GetColorPreference(WellKnownPreference.SchemeColor, GeneralColor);
|
|
||||||
|
|
||||||
public virtual AllowedColors HeaderKeyColor => State.GetColorPreference(WellKnownPreference.HeaderKeyColor, HeaderColor);
|
|
||||||
|
|
||||||
public virtual AllowedColors HeaderSeparatorColor => State.GetColorPreference(WellKnownPreference.HeaderSeparatorColor, HeaderColor);
|
|
||||||
|
|
||||||
public virtual AllowedColors HeaderValueSeparatorColor => State.GetColorPreference(WellKnownPreference.HeaderValueSeparatorColor, HeaderSeparatorColor);
|
|
||||||
|
|
||||||
public virtual AllowedColors HeaderValueColor => State.GetColorPreference(WellKnownPreference.HeaderValueColor, HeaderColor);
|
|
||||||
|
|
||||||
public virtual AllowedColors HeaderColor => State.GetColorPreference(WellKnownPreference.HeaderColor, GeneralColor);
|
|
||||||
|
|
||||||
public virtual AllowedColors GeneralColor => State.GetColorPreference(WellKnownPreference.RequestOrResponseColor);
|
|
||||||
|
|
||||||
public virtual AllowedColors ProtocolColor => State.GetColorPreference(WellKnownPreference.ProtocolColor, GeneralColor);
|
|
||||||
|
|
||||||
public virtual AllowedColors ProtocolNameColor => State.GetColorPreference(WellKnownPreference.ProtocolNameColor, ProtocolColor);
|
|
||||||
|
|
||||||
public virtual AllowedColors ProtocolVersionColor => State.GetColorPreference(WellKnownPreference.ProtocolVersionColor, ProtocolColor);
|
|
||||||
|
|
||||||
public virtual AllowedColors ProtocolSeparatorColor => State.GetColorPreference(WellKnownPreference.ProtocolSeparatorColor, ProtocolColor);
|
|
||||||
|
|
||||||
public virtual AllowedColors StatusColor => State.GetColorPreference(WellKnownPreference.StatusColor, GeneralColor);
|
|
||||||
|
|
||||||
public virtual AllowedColors StatusCodeColor => State.GetColorPreference(WellKnownPreference.StatusCodeColor, StatusColor);
|
|
||||||
|
|
||||||
public virtual AllowedColors StatusReasonPhraseColor => State.GetColorPreference(WellKnownPreference.StatusReaseonPhraseColor, StatusColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue