From 2f1a8d6caa50640925bf634062121391c450a5ed Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Mon, 8 Aug 2022 10:43:49 -0700 Subject: Generate metadata needed to populate update feed Step towards completing 5367 --- src/setup/MetadataTask/GenerateMetadata.cs | 113 +++++++++++++++++++++++++++++ src/setup/MetadataTask/Metadata.cs | 78 ++++++++++++++++++++ src/setup/MetadataTask/MetadataTask.csproj | 14 ++++ 3 files changed, 205 insertions(+) create mode 100644 src/setup/MetadataTask/GenerateMetadata.cs create mode 100644 src/setup/MetadataTask/Metadata.cs create mode 100644 src/setup/MetadataTask/MetadataTask.csproj (limited to 'src/setup/MetadataTask') diff --git a/src/setup/MetadataTask/GenerateMetadata.cs b/src/setup/MetadataTask/GenerateMetadata.cs new file mode 100644 index 00000000..4071c271 --- /dev/null +++ b/src/setup/MetadataTask/GenerateMetadata.cs @@ -0,0 +1,113 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Tasks +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Security.Cryptography; + using System.Text.Json; + using System.Text.Json.Serialization; + using Microsoft.Build.Framework; + using Microsoft.Build.Utilities; + using WixToolset.Data; + using WixToolset.Data.Symbols; + + public class GenerateMetadata : Task + { + private static readonly JsonSerializerOptions SerializerOptions = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + IgnoreNullValues = true, + WriteIndented = true, + Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) }, + }; + + [Required] + public string TargetFile { get; set; } + + [Required] + public string WixpdbFile { get; set; } + + public override bool Execute() + { + var intermediate = Intermediate.Load(this.WixpdbFile); + + var section = intermediate.Sections.Single(); + + if (section.Type != SectionType.Bundle) + { + return false; + } + + (var metadata, var sourceLineNumber) = this.GetBundleMetadata(section); + + if (metadata != null) + { + this.PopulateFileInfo(metadata); + + this.SaveMetadata(metadata, sourceLineNumber); + } + + return true; + } + + private (Metadata, SourceLineNumber) GetBundleMetadata(IntermediateSection section) + { + var bundleSymbol = section.Symbols.OfType().Single(); + + var metadata = new Metadata + { + Type = MetadataType.Burn, + Name = bundleSymbol.Name, + Version = bundleSymbol.Version, + Publisher = bundleSymbol.Manufacturer, + Description = "Installation for " + bundleSymbol.Name, + SupportUrl = bundleSymbol.HelpUrl, + BundleCode = bundleSymbol.BundleId, + UpgradeCode = bundleSymbol.UpgradeCode, + AboutUrl = bundleSymbol.AboutUrl, + Architecture = PlatformToArchitecture(bundleSymbol.Platform), + }; + + return (metadata, bundleSymbol.SourceLineNumbers); + } + + private void PopulateFileInfo(Metadata metadata) + { + var fi = new FileInfo(this.TargetFile); + + using (var sha256 = SHA256.Create()) + using (var stream = fi.OpenRead()) + { + var hash = sha256.ComputeHash(stream); + + metadata.File = fi.Name; + metadata.Created = fi.CreationTimeUtc.ToString("O"); + metadata.Size = fi.Length; + metadata.Sha256 = BitConverter.ToString(hash).Replace("-", String.Empty); + } + } + + private void SaveMetadata(Metadata metadata, SourceLineNumber sourceLineNumber) + { + var metadataFilePath = Path.ChangeExtension(this.TargetFile, "metadata.json"); + + var json = JsonSerializer.Serialize(metadata, SerializerOptions); + + File.WriteAllText(metadataFilePath, json); + } + + private static ArchitectureType PlatformToArchitecture(Platform platform) + { + switch (platform) + { + case Platform.X86: return ArchitectureType.X86; + case Platform.X64: return ArchitectureType.X86; + case Platform.ARM64: return ArchitectureType.X86; + default: throw new ArgumentException($"Unknown platform {platform}"); + } + } + } +} diff --git a/src/setup/MetadataTask/Metadata.cs b/src/setup/MetadataTask/Metadata.cs new file mode 100644 index 00000000..139d9240 --- /dev/null +++ b/src/setup/MetadataTask/Metadata.cs @@ -0,0 +1,78 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Tasks +{ + public enum MetadataType + { + Unknown, + Burn, + Msi, + } + + public enum ArchitectureType + { + Unknown, + Arm64, + X64, + X86, + } + + //{ + // "id": [PackageSymbolId] | [BundleSymbolId], + // "type": "msi" | "burn" + // "name": [ProductName] | [BundleName] + // "locale": [ProductLanguage] | [BundleLanguage] + // "publisher": [Manufacturer] + // "aboutUrl": [ARPURLINFOABOUT] | [AboutUrl] + // "supportUrl": [ARPHELPLINK] | [SupportUrl] + // "description": [ARPCOMMENTS] | "Installation for" + [BundleName] + // "license": [ProductLicense] | [BundleLicense] + // "architecture": "x86" | "x64" | "arm64" + // "size": #### + // "sha256": hex, + // "file": + // "created": + // "productCode": [ProductCode] + // "bundleCode": [BundleId] + // "upgradeCode": [UpgradeCode] + //} + + public class Metadata + { + public string Id { get; set; } + + public MetadataType Type { get; set; } + + public string Name { get; set; } + + public string Version { get; set; } + + public string Locale { get; set; } + + public string Publisher { get; set; } + + public string AboutUrl { get; set; } + + public string SupportUrl { get; set; } + + public string Description { get; set; } + + public string License { get; set; } + + public ArchitectureType Architecture { get; set; } + + public string File { get; set; } + + public long Size { get; set; } + + public string Sha256 { get; set; } + + public string Created { get; set; } + + public string ProductCode { get; set; } + + public string BundleCode { get; set; } + + public string UpgradeCode { get; set; } + } +} diff --git a/src/setup/MetadataTask/MetadataTask.csproj b/src/setup/MetadataTask/MetadataTask.csproj new file mode 100644 index 00000000..2146a591 --- /dev/null +++ b/src/setup/MetadataTask/MetadataTask.csproj @@ -0,0 +1,14 @@ + + + net472 + embedded + + AnyCPU + + + + + + + + -- cgit v1.2.3-55-g6feb