Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/aspnetcore.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPranav K <prkrishn@hotmail.com>2020-04-21 03:25:24 +0300
committerGitHub <noreply@github.com>2020-04-21 03:25:24 +0300
commit6c23730fa8d04e3b9d62d9d16220a02f9b9820b0 (patch)
treee30d403afe01003f87e9913c5bd44c7d643ddd3e /src/Components/WebAssembly
parent202d21431e6f85aac75d3cc81589156ea42ee33c (diff)
Compute SHA256s for blazor.boot.json in parallel (#21021)
* Compute SHA256s for blazor.boot.json in parallel
Diffstat (limited to 'src/Components/WebAssembly')
-rw-r--r--src/Components/WebAssembly/Build/src/Tasks/BlazorGetFileHash.cs135
-rw-r--r--src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.targets6
2 files changed, 139 insertions, 2 deletions
diff --git a/src/Components/WebAssembly/Build/src/Tasks/BlazorGetFileHash.cs b/src/Components/WebAssembly/Build/src/Tasks/BlazorGetFileHash.cs
new file mode 100644
index 0000000000..f10f53a748
--- /dev/null
+++ b/src/Components/WebAssembly/Build/src/Tasks/BlazorGetFileHash.cs
@@ -0,0 +1,135 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Security.Cryptography;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace Microsoft.Build.Tasks
+{
+ /// <summary>
+ /// Computes the checksum for a single file.
+ /// </summary>
+ public sealed class BlazorGetFileHash : Task
+ {
+ internal const string _defaultFileHashAlgorithm = "SHA256";
+ internal const string _hashEncodingBase64 = "base64";
+
+ /// <summary>
+ /// The files to be hashed.
+ /// </summary>
+ [Required]
+ public ITaskItem[] Files { get; set; }
+
+ /// <summary>
+ /// The algorithm. Allowed values: SHA256, SHA384, SHA512. Default = SHA256.
+ /// </summary>
+ public string Algorithm { get; set; } = _defaultFileHashAlgorithm;
+
+ /// <summary>
+ /// The metadata name where the hash is stored in each item. Defaults to "FileHash".
+ /// </summary>
+ public string MetadataName { get; set; } = "FileHash";
+
+ /// <summary>
+ /// The encoding to use for generated hashs. Defaults to "hex". Allowed values = "base64".
+ /// </summary>
+ public string HashEncoding { get; set; } = _hashEncodingBase64;
+
+ /// <summary>
+ /// The hash of the file. This is only set if there was one item group passed in.
+ /// </summary>
+ [Output]
+ public string Hash { get; set; }
+
+ /// <summary>
+ /// The input files with additional metadata set to include the file hash.
+ /// </summary>
+ [Output]
+ public ITaskItem[] Items { get; set; }
+
+ public override bool Execute()
+ {
+ if (!SupportsAlgorithm(Algorithm))
+ {
+ Log.LogError("Unrecognized HashAlgorithm {0}", Algorithm);
+ return false;
+ }
+
+ System.Threading.Tasks.Parallel.ForEach(Files, file =>
+ {
+ if (!File.Exists(file.ItemSpec))
+ {
+ Log.LogError("File not found '{0}", file.ItemSpec);
+ }
+ });
+
+ if (Log.HasLoggedErrors)
+ {
+ return false;
+ }
+
+ System.Threading.Tasks.Parallel.ForEach(Files, file =>
+ {
+ var hash = ComputeHash(Algorithm, file.ItemSpec);
+ file.SetMetadata("FileHashAlgorithm", Algorithm);
+ file.SetMetadata(MetadataName, EncodeHash(hash));
+ });
+
+ Items = Files;
+
+ if (Files.Length == 1)
+ {
+ Hash = Files[0].GetMetadata(MetadataName);
+ }
+
+ return !Log.HasLoggedErrors;
+ }
+
+ internal static string EncodeHash(byte[] hash)
+ {
+ return Convert.ToBase64String(hash);
+ }
+
+ internal static bool SupportsAlgorithm(string algorithmName)
+ => _supportedAlgorithms.Contains(algorithmName);
+
+ internal static byte[] ComputeHash(string algorithmName, string filePath)
+ {
+ using (var stream = File.OpenRead(filePath))
+ using (var algorithm = CreateAlgorithm(algorithmName))
+ {
+ return algorithm.ComputeHash(stream);
+ }
+ }
+
+ private static readonly HashSet<string> _supportedAlgorithms
+ = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
+ {
+ "SHA256",
+ "SHA384",
+ "SHA512",
+ };
+
+ private static HashAlgorithm CreateAlgorithm(string algorithmName)
+ {
+ if (string.Equals(algorithmName, "SHA256", StringComparison.OrdinalIgnoreCase))
+ {
+ return SHA256.Create();
+ }
+ else if (string.Equals(algorithmName, "SHA384", StringComparison.OrdinalIgnoreCase))
+ {
+ return SHA384.Create();
+ }
+ else if (string.Equals(algorithmName, "SHA512", StringComparison.OrdinalIgnoreCase))
+ {
+ return SHA512.Create();
+ }
+
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.targets b/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.targets
index 8c16457068..1b7614bbae 100644
--- a/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.targets
+++ b/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.targets
@@ -1,4 +1,6 @@
<Project>
+ <UsingTask TaskName="BlazorGetFileHash" AssemblyFile="$(_BlazorTasksPath)" />
+
<PropertyGroup>
<BlazorWebAssemblyEnableLinking Condition="'$(BlazorWebAssemblyEnableLinking)' == '' AND '$(Configuration)' != 'Debug'">true</BlazorWebAssemblyEnableLinking>
<BlazorWebAssemblyEnableLinking Condition="'$(BlazorWebAssemblyEnableLinking)' == ''">false</BlazorWebAssemblyEnableLinking>
@@ -153,9 +155,9 @@
<_ExistingBlazorOutputWithTargetPath Include="@(_BlazorOutputWithTargetPath)" Condition="Exists('%(FullPath)')" />
</ItemGroup>
- <GetFileHash Files="@(_ExistingBlazorOutputWithTargetPath)" Algorithm="SHA256" HashEncoding="base64">
+ <BlazorGetFileHash Files="@(_ExistingBlazorOutputWithTargetPath)" Algorithm="SHA256" HashEncoding="base64">
<Output TaskParameter="Items" ItemName="_BlazorOutputWithHash" />
- </GetFileHash>
+ </BlazorGetFileHash>
<ItemGroup>
<_BlazorOutputWithIntegrity Include="@(_BlazorOutputWithHash)">