remove all myget references and inline source-only packages (#887)

This commit is contained in:
Brett V. Forsgren 2020-10-09 08:29:25 -07:00 коммит произвёл GitHub
Родитель 21238cf113
Коммит d96334264a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
28 изменённых файлов: 735 добавлений и 194 удалений

Просмотреть файл

@ -24,6 +24,5 @@
<SystemRuntimeExtensionsVersion>4.3.0</SystemRuntimeExtensionsVersion>
<MicrosoftCodeAnalysisCommonVersion>3.5.0-beta1-final</MicrosoftCodeAnalysisCommonVersion>
<MicrosoftCodeAnalysisWorkspacesCommonVersion>3.5.0-beta1-final</MicrosoftCodeAnalysisWorkspacesCommonVersion>
<TaskExtensionsVersion>0.1.8580001</TaskExtensionsVersion>
</PropertyGroup>
</Project>

Просмотреть файл

@ -22,7 +22,7 @@ To install the latest preview build from master, first uninstall the existing ve
Then, install from the preview package feed:
```console
> dotnet tool install -g --add-source "https://dotnet.myget.org/F/dotnet-try/api/v3/index.json" Microsoft.dotnet-try
> dotnet tool install -g --add-source "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" Microsoft.dotnet-try
```
## Getting Started

Просмотреть файл

@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
namespace Recipes
{
public static class EnvironmentExtensions
{
public static bool IsTest(this IHostEnvironment hostingEnvironment) =>
hostingEnvironment.EnvironmentName == "test";
public static IWebHostBuilder UseTestEnvironment(this IWebHostBuilder builder) =>
builder.UseEnvironment("test");
}
}

Просмотреть файл

@ -10,22 +10,16 @@
<EmbeddedResource Remove="TestResults\**" />
<None Remove="TestResults\**" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\WorkspaceServer\(Recipes)\JsonSerializationExtensions.cs" />
<Compile Include="..\WorkspaceServer.Tests\(Recipes)\HttpResponseMessageAssertions.cs" />
<Compile Include="..\WorkspaceServer.Tests\(Recipes)\HttpResponseMessageExtensions.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.12" />
<PackageReference Include="HttpResponseMessageAssertions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="HttpResponseMessageExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="JsonSerializationExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Pocket.Disposable" Version="1.0.5">

Просмотреть файл

@ -27,9 +27,5 @@
<PackageReference Include="System.Runtime.Extensions" Version="$(SystemRuntimeExtensionsVersion)" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="3.6.0" />
<PackageReference Include="TaskExtensions" Version="$(TaskExtensionsVersion)">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,26 @@
using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace Recipes
{
internal class BadRequestOnInvalidModelFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(
context.ModelState
.Values
.SelectMany(e => e.Errors
.Select(ee => ee.ErrorMessage)));
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
}
}

Просмотреть файл

@ -0,0 +1,329 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using Microsoft.DotNet.Try.Protocol;
using Microsoft.DotNet.Try.Protocol.ClientApi;
using Microsoft.DotNet.Try.Protocol.ClientApi.GitHub;
namespace Recipes
{
internal static class ClientConfigurationExtensions
{
private static readonly Regex OptionalRouteFilter = new Regex(@"/\{.+\?\}", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
private static string ToSha256(string value)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
var inputBytes = Encoding.UTF8.GetBytes(value);
byte[] hash;
using (var sha256 = SHA256.Create())
{
hash = sha256.ComputeHash(inputBytes);
}
return Convert.ToBase64String(hash);
}
public static string ComputeHash(this RequestDescriptors links)
{
return ToSha256(links.ToJson());
}
public static string BuildUrl(this RequestDescriptor requestDescriptor, Dictionary<string, object> context = null)
{
var url = requestDescriptor.Href;
if (requestDescriptor.Templated && context?.Count > 0)
{
foreach (var entry in context)
{
var filter = new Regex(@"\{" + entry.Key + @"\??\}", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
url = filter.Replace(url, $"{UrlEncode(entry.Value.ToString())}");
}
}
return OptionalRouteFilter.Replace(url, string.Empty);
}
public static string BuildQueryString(this RequestDescriptor requestDescriptor, Dictionary<string, object> context = null)
{
var parts = new List<string>();
if (context?.Count > 0)
{
if (context.TryGetValue("hostOrigin", out var hostOrigin))
{
parts.Add($"hostOrigin={UrlEncode(hostOrigin.ToString())}");
}
foreach (var property in requestDescriptor.Properties ?? Enumerable.Empty<RequestDescriptorProperty>())
{
if (context.TryGetValue(property.Name, out var propertyValue))
{
parts.Add($"{property.Name}={UrlEncode(propertyValue.ToString())}");
}
}
}
return string.Join("&", parts);
}
public static HttpRequestMessage BuildRequest(this RequestDescriptor requestDescriptor, Dictionary<string, object> context = null)
{
var fullUrl = requestDescriptor.BuildFullUri(context);
var request = new HttpRequestMessage
{
RequestUri = new Uri(fullUrl, UriKind.RelativeOrAbsolute)
};
switch (requestDescriptor.Method)
{
case "POST":
request.Method = HttpMethod.Post;
break;
case "DELETE":
request.Method = HttpMethod.Delete;
break;
case "PUT":
request.Method = HttpMethod.Put;
break;
case "HEAD":
request.Method = HttpMethod.Head;
break;
case "OPTIONS":
request.Method = HttpMethod.Options;
break;
case "TRACE":
request.Method = HttpMethod.Trace;
break;
default:
request.Method = HttpMethod.Get;
break;
}
return request;
}
public static string BuildFullUri(this RequestDescriptor requestDescriptor, Dictionary<string, object> context = null)
{
var url = requestDescriptor.BuildUrl(context);
var queryString = requestDescriptor.BuildQueryString(context);
var fullUrl = url;
if (!string.IsNullOrWhiteSpace(queryString))
{
var joinSymbol = "?";
if (url.IndexOf("?", StringComparison.InvariantCultureIgnoreCase) >= 0)
{
joinSymbol = "&";
}
fullUrl = $"{url}{joinSymbol}{queryString}";
}
return fullUrl;
}
public static HttpRequestMessage BuildLoadFromRequest(this ClientConfiguration configuration, string codeUrl, string hostOrigin)
{
var api = configuration.Links.Snippet;
var context = new Dictionary<string, object>
{
{ "from", codeUrl }
};
var request = BuildRequestWithHeaders(configuration, api, hostOrigin, context);
return request;
}
private static HttpRequestMessage BuildRequestWithHeaders(this ClientConfiguration configuration, RequestDescriptor requestDescriptor, string hostOrigin, Dictionary<string, object> context = null)
{
var safeContext = context ?? new Dictionary<string, object>();
if (hostOrigin != null)
{
safeContext["hostOrigin"] = hostOrigin;
}
var request = requestDescriptor.BuildRequest(safeContext);
configuration.AddConfigurationVersionIdHeader(request);
configuration.AddTimeoutHeader(request, requestDescriptor);
return request;
}
public static HttpRequestMessage BuildLoadFromGistRequest(this ClientConfiguration configuration, string gist, string hash = null, string workspaceType = null,
bool? extractBuffers = null, string hostOrigin = null)
{
var api = configuration.Links.LoadFromGist;
var context = new Dictionary<string, object>
{
{ "gistId", gist }
};
if (hash != null)
{
context["commitHash"] = hash;
}
if (workspaceType != null)
{
context["workspaceType"] = workspaceType;
}
if (extractBuffers != null)
{
context["extractBuffers"] = extractBuffers;
}
return BuildRequestWithHeaders(configuration, api, hostOrigin, context);
}
public static HttpRequestMessage BuildRegionFromFilesRequest(this ClientConfiguration configuration, IEnumerable<SourceFile> files, string hostOrigin, string requestId = null)
{
var api = configuration.Links.RegionsFromFiles;
var request = BuildRequestWithHeaders(configuration, api, hostOrigin);
var payload = new CreateRegionsFromFilesRequest(requestId ?? (Guid.NewGuid().ToString()), files?.ToArray());
SetRequestContent(payload, request);
return request;
}
public static HttpRequestMessage BuildProjectFromGistRequest(this ClientConfiguration configuration, string gistId, string projectTemplate, string hostOrigin, string hash = null, string requestId = null)
{
var api = configuration.Links.ProjectFromGist;
var request = BuildRequestWithHeaders(configuration, api, hostOrigin);
var payload = new CreateProjectFromGistRequest(requestId ?? (Guid.NewGuid().ToString()), gistId, projectTemplate, hash);
SetRequestContent(payload, request);
return request;
}
public static HttpRequestMessage BuildCompletionRequest(this ClientConfiguration configuration, object workspaceRequest, string hostOrigin)
{
var api = configuration.Links.Completion;
var request = BuildRequestWithHeaders(configuration, api, hostOrigin);
SetRequestContent(workspaceRequest, request);
return request;
}
public static HttpRequestMessage BuildCompileRequest(this ClientConfiguration configuration, object workspaceRequest, string hostOrigin)
{
var api = configuration.Links.Compile;
var request = BuildRequestWithHeaders(configuration, api, hostOrigin);
SetRequestContent(workspaceRequest, request);
return request;
}
public static HttpRequestMessage BuildSignatureHelpRequest(this ClientConfiguration configuration, object workspaceRequest, string hostOrigin)
{
var api = configuration.Links.SignatureHelp;
var request = BuildRequestWithHeaders(configuration, api, hostOrigin);
SetRequestContent(workspaceRequest, request);
return request;
}
public static HttpRequestMessage BuildDiagnosticsRequest(this ClientConfiguration configuration, object workspace, string hostOrigin)
{
var api = configuration.Links.Diagnostics;
var request = BuildRequestWithHeaders(configuration, api, hostOrigin);
SetRequestContent(workspace, request);
return request;
}
public static HttpRequestMessage BuildRunRequest(this ClientConfiguration configuration, object workspaceRequest, string hostOrigin)
{
var api = configuration.Links.Run;
var request = BuildRequestWithHeaders(configuration, api, hostOrigin);
SetRequestContent(workspaceRequest, request);
return request;
}
public static HttpRequestMessage BuildVersionRequest(this ClientConfiguration configuration, string hostOrigin)
{
var api = configuration.Links.Version;
return BuildRequestWithHeaders(configuration, api, hostOrigin);
}
public static HttpRequestMessage BuildGetPackagesRequest(this ClientConfiguration configuration, string packageName, string packageVersion, string hostOrigin)
{
var api = configuration.Links.GetPackage;
var context = new Dictionary<string, object>
{
{ "name", packageName },
{ "version", packageVersion }
};
var request = BuildRequestWithHeaders(configuration, api, hostOrigin, context);
return request;
}
private static string UrlEncode(string source)
{
return HttpUtility.UrlEncode(HttpUtility.UrlDecode(source));
}
private static void AddConfigurationVersionIdHeader(this ClientConfiguration configuration, HttpRequestMessage request)
{
request.Headers.Remove("ClientConfigurationVersionId");
request.Headers.Add("ClientConfigurationVersionId", configuration.VersionId);
}
private static void AddTimeoutHeader(this ClientConfiguration configuration, HttpRequestMessage request, RequestDescriptor requestDescriptor = null)
{
request.Headers.Remove("Timeout");
var timeoutMs = configuration.DefaultTimeoutMs.ToString(CultureInfo.InvariantCulture);
if (requestDescriptor != null && requestDescriptor.TimeoutMs > 0)
{
timeoutMs = requestDescriptor.TimeoutMs.ToString(CultureInfo.InvariantCulture);
}
request.Headers.Add("Timeout", timeoutMs);
}
private static void SetRequestContent(object content, HttpRequestMessage request)
{
switch (content)
{
case string text:
request.Content = new JsonContent(text);
break;
default:
request.Content = new JsonContent(content);
break;
}
}
}
}

Просмотреть файл

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
namespace Recipes
{
internal static class DictionaryExtensions
{
/// <summary>
/// Adds a key/value pair to the dictionary if the key does not already exist.
/// </summary>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <param name="dictionary">The dictionary.</param>
/// <param name="key">The key of the element to add.</param>
/// <param name="valueFactory">The function used to generate a value for the key.</param>
/// <returns>
/// The value for the key. This will be either the existing value for the key if the key is already in the dictionary, or the new value for the key as returned by valueFactory if the key was not in the dictionary.
/// </returns>
/// <exception cref="System.ArgumentNullException">dictionary</exception>
public static TValue GetOrAdd<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary,
TKey key,
Func<TKey, TValue> valueFactory)
{
if (dictionary == null)
{
throw new ArgumentNullException(nameof(dictionary));
}
if (valueFactory == null)
{
throw new ArgumentNullException(nameof(valueFactory));
}
TValue value;
if (dictionary.TryGetValue(key, out value))
{
return value;
}
value = valueFactory(key);
dictionary.Add(key, value);
return value;
}
}
}

Просмотреть файл

@ -0,0 +1,22 @@
using System.Net.Http;
using System.Text;
namespace Recipes
{
internal class JsonContent : StringContent
{
public JsonContent(object content)
: base(content.ToJson(),
Encoding.UTF8,
"application/json")
{
}
public JsonContent(string content)
: base(content,
Encoding.UTF8,
"application/json")
{
}
}
}

Просмотреть файл

@ -0,0 +1,48 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
namespace Recipes
{
#if !RecipesProject
[DebuggerStepThrough]
#endif
internal partial class VersionSensor
{
private static readonly Lazy<BuildInfo> buildInfo = new Lazy<BuildInfo>(() =>
{
var assembly = typeof(VersionSensor).GetTypeInfo().Assembly;
var info = new BuildInfo
{
AssemblyName = assembly.GetName().Name,
AssemblyInformationalVersion = assembly
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
.InformationalVersion,
AssemblyVersion = assembly.GetName().Version.ToString(),
BuildDate = new FileInfo(new Uri(assembly.CodeBase).LocalPath).CreationTimeUtc.ToString("o")
};
AssignServiceVersionTo(info);
return info;
});
public static BuildInfo Version()
{
return buildInfo.Value;
}
public class BuildInfo
{
public string AssemblyVersion { get; set; }
public string BuildDate { get; set; }
public string AssemblyInformationalVersion { get; set; }
public string AssemblyName { get; set; }
public string ServiceVersion { get; set; }
}
static partial void AssignServiceVersionTo(BuildInfo buildInfo);
}
}

Просмотреть файл

@ -42,34 +42,11 @@
<ItemGroup>
<Compile Include="..\Microsoft.DotNet.Interactive\Utility\DirectoryUtility.cs" Link="%28Recipes%29\DirectoryUtility.cs" />
<Compile Include="..\Microsoft.DotNet.Interactive\Utility\DisposableDirectory.cs" Link="%28Recipes%29\DisposableDirectory.cs" />
<Compile Include="..\WorkspaceServer\(Recipes)\JsonSerializationExtensions.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BadRequestOnInvalidModelFilter" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="ClientConfiguration" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Clockwise" Version="1.0.261-beta" />
<PackageReference Include="ConfigurationExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="DictionaryExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="EnvironmentExtensions" Version="0.1.9120003">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="LoggerExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Markdig" Version="0.17.1" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Blazor.Server" Version="3.0.0-preview7.19365.7" />
@ -97,14 +74,6 @@
</PackageReference>
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20359.2" />
<PackageReference Include="System.Reactive" Version="4.4.1" />
<PackageReference Include="TaskExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="VersionSensor" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -18,10 +18,6 @@
<ItemGroup>
<PackageReference Include="Assent" Version="1.3.1" />
<PackageReference Include="FluentAssertions" Version="5.10.0" />
<PackageReference Include="JsonSerializationExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Pocket.Disposable" Version="1.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

Просмотреть файл

@ -18,7 +18,6 @@
<dependency id="System.Runtime.Extensions" version="$SystemRuntimeExtensionsVersion$" />
<dependency id="Microsoft.CodeAnalysis.Common" version="$MicrosoftCodeAnalysisCommonVersion$" />
<dependency id="Microsoft.CodeAnalysis.Workspaces.Common" version="$MicrosoftCodeAnalysisWorkspacesCommonVersion$" />
<dependency id="TaskExtensions" version="$TaskExtensionsVersion$" />
</group>
</dependencies>
</metadata>

Просмотреть файл

@ -13,10 +13,6 @@
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="JsonSerializationExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis" Version="3.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.6.0" />

Просмотреть файл

@ -14,10 +14,6 @@
<ItemGroup>
<PackageReference Include="Assent" Version="1.3.1" />
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="JsonSerializationExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis" Version="3.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.6.0" />

Просмотреть файл

@ -9,7 +9,6 @@
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
<add key="dotnet-tools" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" />
<add key="dotnet5" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json" />
<add key="dotnet-try" value="https://dotnet.myget.org/F/dotnet-try/api/v3/index.json" />
<add key="dotnet-tools" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" />
<add key="MachineLearning" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/MachineLearning/nuget/v3/index.json" />
</packageSources>

Просмотреть файл

@ -0,0 +1,59 @@
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using FluentAssertions;
using FluentAssertions.Execution;
using FluentAssertions.Primitives;
namespace Recipes
{
[DebuggerStepThrough]
internal class HttpResponseMessageAssertions : ObjectAssertions
{
private readonly HttpResponseMessage _subject;
public HttpResponseMessageAssertions(HttpResponseMessage subject) : base(subject)
{
_subject = subject ?? throw new ArgumentNullException(nameof(subject));
}
public AndConstraint<HttpResponseMessageAssertions> BeSuccessful()
{
string content = "";
if (!_subject.IsSuccessStatusCode)
{
content = _subject.Content.ReadAsStringAsync().Result;
}
Execute.Assertion
.ForCondition(_subject.IsSuccessStatusCode)
.FailWith("Expected successful response but received: {0}\nResponse body:\n{1}", _subject, content);
return new AndConstraint<HttpResponseMessageAssertions>(this);
}
public AndConstraint<HttpResponseMessageAssertions> BeNotFound()
{
Execute.Assertion
.ForCondition(_subject.StatusCode == HttpStatusCode.NotFound)
.FailWith($"Expected Forbidden response but received: {_subject.ToString().Replace("{", "{{").Replace("}", "}}")}");
return new AndConstraint<HttpResponseMessageAssertions>(this);
}
}
internal static class HttpResponseMessageAssertionExtensions
{
public static HttpResponseMessage EnsureSuccess(this HttpResponseMessage subject)
{
subject.Should().BeSuccessful();
return subject;
}
public static HttpResponseMessageAssertions Should(this HttpResponseMessage subject) =>
new HttpResponseMessageAssertions(subject);
}
}

Просмотреть файл

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Net.Http.Headers;
using Newtonsoft.Json;
namespace Recipes
{
internal static class HttpResponseMessageExtensions
{
public static async Task<T> DeserializeAs<T>(this HttpResponseMessage response)
{
var json = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(json);
}
public static IEnumerable<SetCookieHeaderValue> GetSetCookieHeaderValues(this HttpResponseMessage subject)
{
subject = subject ?? throw new ArgumentNullException(nameof(subject));
IEnumerable<string> values;
if (!subject.Headers.TryGetValues("Set-Cookie", out values))
{
return Enumerable.Empty<SetCookieHeaderValue>();
}
return SetCookieHeaderValue.ParseList(values.ToList()).ToList();
}
public static string GetSetCookieHeaderValue(this HttpResponseMessage subject, string cookieName)
{
subject = subject ?? throw new ArgumentNullException(nameof(subject));
cookieName = cookieName ?? throw new ArgumentNullException(nameof(cookieName));
return subject
.GetSetCookieHeaderValues()
.FirstOrDefault(c => c.Name == cookieName)
?.Value
.ToString();
}
}
}

Просмотреть файл

@ -14,6 +14,10 @@
<None Remove="TestResults\**" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\WorkspaceServer\(Recipes)\JsonSerializationExtensions.cs" />
</ItemGroup>
<ItemGroup>
<None Include="TestProjects\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
@ -21,25 +25,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AsyncLock" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Assent" Version="1.3.1" />
<PackageReference Include="Clockwise" Version="1.0.261-beta" />
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="HttpResponseMessageAssertions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="HttpResponseMessageExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="JsonSerializationExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis" Version="3.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.6.0" />

Просмотреть файл

@ -0,0 +1,41 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Recipes
{
internal class AsyncLock
{
private readonly AsyncSemaphore _semaphore;
private readonly Task<Releaser> _releaser;
public AsyncLock()
{
_semaphore = new AsyncSemaphore(1);
_releaser = Task.FromResult(new Releaser(this));
}
public Task<Releaser> LockAsync()
{
var wait = _semaphore.WaitAsync();
return wait.IsCompleted
? _releaser
: wait.ContinueWith((_, state) => new Releaser((AsyncLock) state),
this, CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
}
public struct Releaser : IDisposable
{
private readonly AsyncLock _toRelease;
internal Releaser(AsyncLock toRelease)
{
_toRelease = toRelease ?? throw new ArgumentNullException(nameof(toRelease));
}
public void Dispose() => _toRelease?._semaphore.Release();
}
}
}

Просмотреть файл

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Recipes
{
internal class AsyncSemaphore
{
private static readonly Task _completed = Task.FromResult(true);
private readonly Queue<TaskCompletionSource<bool>> _waiters = new Queue<TaskCompletionSource<bool>>();
private int m_currentCount;
public AsyncSemaphore(int initialCount)
{
if (initialCount < 0)
{
throw new ArgumentOutOfRangeException(nameof(initialCount));
}
m_currentCount = initialCount;
}
public Task WaitAsync()
{
lock (_waiters)
{
if (m_currentCount > 0)
{
--m_currentCount;
return _completed;
}
else
{
var waiter = new TaskCompletionSource<bool>();
_waiters.Enqueue(waiter);
return waiter.Task;
}
}
}
public void Release()
{
TaskCompletionSource<bool> toRelease = null;
lock (_waiters)
{
if (_waiters.Count > 0)
{
toRelease = _waiters.Dequeue();
}
else
{
++m_currentCount;
}
}
toRelease?.SetResult(true);
}
}
}

Просмотреть файл

@ -0,0 +1,13 @@
using Clockwise;
using Pocket;
namespace Recipes
{
public static class ConfirmationLoggerExtensions
{
internal static void Complete(
this ConfirmationLogger logger,
Budget budget) =>
logger.Succeed("Completed with {budget}", budget);
}
}

Просмотреть файл

@ -0,0 +1,17 @@
using System;
using Newtonsoft.Json;
namespace Recipes
{
internal static class JsonSerializationExtensions
{
public static string ToJson(this object source) =>
JsonConvert.SerializeObject(source);
public static T FromJsonTo<T>(this string json) =>
JsonConvert.DeserializeObject<T>(json);
public static object FromJsonTo(this string json, Type type, JsonSerializerSettings settings = null) =>
JsonConvert.DeserializeObject(json, type, settings);
}
}

Просмотреть файл

@ -38,22 +38,10 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AsyncLock" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Buildalyzer" Version="3.0.0" />
<PackageReference Include="Buildalyzer.Workspaces" Version="3.0.0" />
<PackageReference Include="Clockwise" Version="1.0.261-beta" />
<PackageReference Include="DictionaryExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="FSharp.Core" />
<PackageReference Include="JsonSerializationExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="3.6.0" />
@ -69,24 +57,8 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="ConfirmationLoggerExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="DictionaryExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="JsonSerializationExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="System.ComponentModel.Annotations" Version="4.6.0" />
<PackageReference Include="System.Runtime.InteropServices" Version="4.3.0" />
<PackageReference Include="TaskExtensions" Version="0.1.5650001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="PocketLogger" Version="0.3.0">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
@ -95,10 +67,6 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> -->
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
<PackageReference Include="TaskExtensions" Version="0.1.8580001">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -294,11 +294,3 @@ stages:
enableSymbolValidation: false
# SourceLink improperly looks for generated files. See https://github.com/dotnet/arcade/issues/3069
enableSourceLinkValidation: false
#---------------------------------------------------------------------------------------------------------------------#
# Package upload #
#---------------------------------------------------------------------------------------------------------------------#
- ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
- template: eng/upload/upload-packages.yml
parameters:
branchToUpload: refs/heads/main

Просмотреть файл

@ -9,7 +9,6 @@
<NuspecProperty Include="SystemDiagnosticsProcessVersion=$(SystemDiagnosticsProcessVersion)" />
<NuspecProperty Include="MicrosoftCodeAnalysisCommonVersion=$(MicrosoftCodeAnalysisCommonVersion)" />
<NuspecProperty Include="MicrosoftCodeAnalysisWorkspacesCommonVersion=$(MicrosoftCodeAnalysisWorkspacesCommonVersion)" />
<NuspecProperty Include="TaskExtensionsVersion=$(TaskExtensionsVersion)" />
<NuspecProperty Include="SystemRuntimeExtensionsVersion=$(SystemRuntimeExtensionsVersion)" />
</ItemGroup>

Просмотреть файл

@ -1,44 +0,0 @@
[CmdletBinding(PositionalBinding=$false)]
param (
[string]$apiKey,
[string]$feedUrl,
[string]$packagesDir
)
Set-StrictMode -version 2.0
$ErrorActionPreference = "Stop"
try {
$packagePatterns = @(
"Microsoft.dotnet-try.*.nupkg",
"Microsoft.DotNet.Try.ProjectTemplate.Tutorial.*.nupkg",
"MLS.Blazor.*.nupkg",
"MLS.WasmCodeRunner.*.nupkg",
"WorkspaceServer.*.nupkg"
)
$errors = 0
foreach ($pattern in $packagePatterns) {
foreach ($packageName in (Get-Item "$packagesDir\$pattern")) {
$fullPath = $packageName.ToString()
Write-Host "Uploading package $fullPath."
$response = Invoke-WebRequest -Uri $feedUrl -Headers @{"X-NuGet-ApiKey"=$apiKey} -ContentType "multipart/form-data" -InFile "$fullPath" -Method Post -UseBasicParsing
if ($response.StatusCode -ne 201) {
Write-Host "Failed to upload package. Status code: $response.StatusCode."
$errors++
}
else {
Write-Host "Done."
}
}
}
exit $errors
}
catch {
Write-Host $_
Write-Host $_.Exception
Write-Host $_.ScriptStackTrace
exit 1
}

Просмотреть файл

@ -1,27 +0,0 @@
parameters:
branchToUpload: ''
stages:
- stage: upload
dependsOn: build
displayName: Upload packages to MyGet
jobs:
- job: Upload_Packages
pool:
vmImage: windows-2019
variables:
- group: dotnet-try-myget-api-keys
- name: FeedUrl
value: 'https://dotnet.myget.org/F/dotnet-try/api/v2/package'
steps:
- task: DownloadBuildArtifacts@0
displayName: Download package artifacts
inputs:
buildType: current
artifactName: packages
- task: PowerShell@2
displayName: Upload packages to MyGet
inputs:
filePath: $(Build.SourcesDirectory)/eng/upload/scripts/UploadPackages.ps1
arguments: -apiKey $(MyGetAPIKey) -feedUrl $(FeedUrl) -packagesDir $(Build.ArtifactStagingDirectory)\packages\Shipping
condition: and(succeeded(), eq(variables['Build.SourceBranch'], '${{ parameters.branchToUpload }}'))