From 9e7ffaec1f204e950e0ac3d1044a88e2f348771a Mon Sep 17 00:00:00 2001 From: David Bennett Date: Tue, 23 Dec 2025 11:43:58 -0800 Subject: [PATCH] Add font support --- src/WingetCreateCLI/Commands/BaseCommand.cs | 9 ++- src/WingetCreateCLI/Commands/NewCommand.cs | 60 +++++++++++++++++-- .../Commands/NewLocaleCommand.cs | 3 +- src/WingetCreateCLI/Commands/SubmitCommand.cs | 7 ++- src/WingetCreateCLI/Commands/UpdateCommand.cs | 5 +- .../Commands/UpdateLocaleCommand.cs | 3 +- src/WingetCreateCLI/WingetCreateCLI.csproj | 40 ++++++------- src/WingetCreateCore/Common/Constants.cs | 5 ++ src/WingetCreateCore/Common/GitHub.cs | 25 ++++---- src/WingetCreateCore/Common/PackageParser.cs | 54 +++++++++++++++++ src/WingetCreateCore/Common/Utils.cs | 5 +- .../Models/DefaultLocaleManifestModels.cs | 4 +- .../Models/InstallerManifestModels.cs | 12 +++- .../Models/LocaleManifestModels.cs | 4 +- .../Models/SingletonManifestModels.cs | 12 +++- .../Models/VersionManifestModels.cs | 4 +- .../UnitTests/GitHubTests.cs | 3 +- .../UnitTests/UpdateCommandTests.cs | 6 +- 18 files changed, 201 insertions(+), 60 deletions(-) diff --git a/src/WingetCreateCLI/Commands/BaseCommand.cs b/src/WingetCreateCLI/Commands/BaseCommand.cs index d1891bf4..88fd2688 100644 --- a/src/WingetCreateCLI/Commands/BaseCommand.cs +++ b/src/WingetCreateCLI/Commands/BaseCommand.cs @@ -166,10 +166,12 @@ public async Task LoadGitHubClient(bool requireToken = false) /// Creates a formatted directory of manifest files from the manifest object models and saves the directory to a local path. /// /// Wrapper object for manifest object models. + /// Manifest root name. /// Output directory where the manifests are saved locally. /// Path to manifest directory. protected static string SaveManifestDirToLocalPath( Manifests manifests, + string manifestRoot, string outputDir) { VersionManifest versionManifest = manifests.VersionManifest; @@ -180,7 +182,7 @@ protected static string SaveManifestDirToLocalPath( outputDir = Environment.ExpandEnvironmentVariables(outputDir); string version = versionManifest.PackageVersion; string packageId = versionManifest.PackageIdentifier; - string manifestDir = Utils.GetAppManifestDirPath(packageId, version); + string manifestDir = Utils.GetAppManifestDirPath(packageId, version, manifestRoot); string fullDirPath = Path.GetFullPath(Path.Combine(outputDir, manifestDir)); try @@ -739,11 +741,12 @@ protected async Task CheckGitHubTokenAndSetClient() /// Submits a pull request with multifile manifests using the user's GitHub access token. /// /// Wrapper object for manifest object models to be submitted. + /// Manifest root name. /// Optional parameter specifying the title for the pull request. /// Optional parameter specifying whether the new submission should replace an existing manifest. /// Optional parameter specifying the version of the manifest to be replaced. /// A representing the success of the asynchronous operation. - protected async Task GitHubSubmitManifests(Manifests manifests, string prTitle = null, bool shouldReplace = false, string replaceVersion = null) + protected async Task GitHubSubmitManifests(Manifests manifests, string manifestRoot = Constants.WingetManifestRoot, string prTitle = null, bool shouldReplace = false, string replaceVersion = null) { // Community repo only supports yaml submissions. if (this.WingetRepo == DefaultWingetRepo && @@ -765,7 +768,7 @@ protected async Task GitHubSubmitManifests(Manifests manifests, string prT try { - PullRequest pullRequest = await this.GitHubClient.SubmitPullRequestAsync(manifests, this.SubmitPRToFork, prTitle, shouldReplace, replaceVersion); + PullRequest pullRequest = await this.GitHubClient.SubmitPullRequestAsync(manifests, this.SubmitPRToFork, manifestRoot, prTitle, shouldReplace, replaceVersion); this.PullRequestNumber = pullRequest.Number; PullRequestEvent pullRequestEvent = new PullRequestEvent { IsSuccessful = true, PullRequestNumber = pullRequest.Number }; TelemetryManager.Log.WriteEvent(pullRequestEvent); diff --git a/src/WingetCreateCLI/Commands/NewCommand.cs b/src/WingetCreateCLI/Commands/NewCommand.cs index 6f82369f..66df3546 100644 --- a/src/WingetCreateCLI/Commands/NewCommand.cs +++ b/src/WingetCreateCLI/Commands/NewCommand.cs @@ -25,6 +25,7 @@ namespace Microsoft.WingetCreateCLI.Commands using Microsoft.WingetCreateCore.Models.DefaultLocale; using Microsoft.WingetCreateCore.Models.Installer; using Microsoft.WingetCreateCore.Models.Version; + using Newtonsoft.Json.Schema.Generation; using Sharprompt; /// @@ -41,7 +42,20 @@ public class NewCommand : BaseCommand /// /// Installer type file extensions that are supported. /// - private static readonly string[] SupportedInstallerTypeExtensions = new[] { ".msix", ".msi", ".exe", ".msixbundle", ".appx", ".appxbundle" }; + private static readonly string[] SupportedInstallerTypeExtensions = + [ + ".msix", + ".msi", + ".exe", + ".msixbundle", + ".appx", + ".appxbundle", + ".otf", // OpenType Font + ".ttf", // TrueType Font + ".fnt", // Font + ".ttc", // TrueType Font Collection + ".otc", // OpenType Font Collection + ]; /// /// Gets the usage examples for the New command. @@ -111,6 +125,7 @@ public override async Task Execute() Prompt.Symbols.Prompt = new Symbol(string.Empty, string.Empty); Manifests manifests = new Manifests(); + var isFontPackage = false; if (!this.InstallerUrls.Any()) { @@ -163,6 +178,10 @@ public override async Task Execute() .ToList(); int extractedFilesCount = extractedFiles.Count(); + + // Font packages have a single installer entry with many nested installer files. + isFontPackage = PackageParser.IsFontPackage(extractedFiles); + List selectedInstallers; if (extractedFilesCount == 0) @@ -174,23 +193,51 @@ public override async Task Execute() { selectedInstallers = extractedFiles; } + else if (isFontPackage) + { + // If this is a font package, every installer is intended to be installed. + selectedInstallers = extractedFiles; + } else { selectedInstallers = Prompt.MultiSelect(Resources.SelectInstallersFromZip_Message, extractedFiles, minimum: 1).ToList(); } - foreach (var installer in selectedInstallers) + if (isFontPackage) { + // If every installer is a single font package, we can convert the entire package into a single font nested installer. + List nestedInstallerFiles = []; + foreach (var fontFile in selectedInstallers) + { + nestedInstallerFiles.Add(new NestedInstallerFile { RelativeFilePath = fontFile }); + } + installerUpdateList.Add( new InstallerMetadata { InstallerUrl = installerUrl, PackageFile = packageFile, - NestedInstallerFiles = new List { new NestedInstallerFile { RelativeFilePath = installer } }, + NestedInstallerFiles = nestedInstallerFiles, + OverrideArchitecture = Architecture.Neutral, IsZipFile = true, ExtractedDirectory = extractDirectory, }); } + else + { + foreach (var installer in selectedInstallers) + { + installerUpdateList.Add( + new InstallerMetadata + { + InstallerUrl = installerUrl, + PackageFile = packageFile, + NestedInstallerFiles = new List { new NestedInstallerFile { RelativeFilePath = installer } }, + IsZipFile = true, + ExtractedDirectory = extractDirectory, + }); + } + } } else { @@ -276,7 +323,8 @@ public override async Task Execute() this.OutputDir = Directory.GetCurrentDirectory(); } - SaveManifestDirToLocalPath(manifests, this.OutputDir); + var manifestRoot = isFontPackage ? Constants.WingetFontRoot : Constants.WingetManifestRoot; + SaveManifestDirToLocalPath(manifests, manifestRoot, this.OutputDir); if (isManifestValid && Prompt.Confirm(Resources.ConfirmGitHubSubmitManifest_Message)) { @@ -488,13 +536,13 @@ private static void PromptForPortableFieldsIfApplicable(Installer installer) /// /// Merge nested installer files into a single installer if: - /// 1. Matching installers have NestedInstallerType: portable. + /// 1. Matching installers have NestedInstallerType: portable or font /// 2. Matching installers have the same architecture. /// 3. Matching installers have the same hash. /// private static void MergeNestedInstallerFilesIfApplicable(InstallerManifest installerManifest) { - var nestedPortableInstallers = installerManifest.Installers.Where(i => i.NestedInstallerType == NestedInstallerType.Portable).ToList(); + var nestedPortableInstallers = installerManifest.Installers.Where(i => (i.NestedInstallerType == NestedInstallerType.Portable)).ToList(); //// || (i.NestedInstallerType == NestedInstallerType.Font)).ToList(); var mergeableInstallersList = nestedPortableInstallers.GroupBy(i => i.Architecture + i.InstallerSha256).ToList(); foreach (var installers in mergeableInstallersList) { diff --git a/src/WingetCreateCLI/Commands/NewLocaleCommand.cs b/src/WingetCreateCLI/Commands/NewLocaleCommand.cs index 92995a48..7223b77b 100644 --- a/src/WingetCreateCLI/Commands/NewLocaleCommand.cs +++ b/src/WingetCreateCLI/Commands/NewLocaleCommand.cs @@ -239,7 +239,8 @@ public override async Task Execute() this.OutputDir = Directory.GetCurrentDirectory(); } - string manifestDirectoryPath = SaveManifestDirToLocalPath(originalManifests, this.OutputDir); + // TODO: Need to discern font root manifests. Assume default root for now. + string manifestDirectoryPath = SaveManifestDirToLocalPath(originalManifests, Constants.WingetManifestRoot, this.OutputDir); if (ValidateManifest(manifestDirectoryPath, this.Format)) { diff --git a/src/WingetCreateCLI/Commands/SubmitCommand.cs b/src/WingetCreateCLI/Commands/SubmitCommand.cs index b5c6535c..7043d5da 100644 --- a/src/WingetCreateCLI/Commands/SubmitCommand.cs +++ b/src/WingetCreateCLI/Commands/SubmitCommand.cs @@ -9,6 +9,7 @@ namespace Microsoft.WingetCreateCLI.Commands using System.Threading.Tasks; using CommandLine; using CommandLine.Text; + using Microsoft.VisualBasic; using Microsoft.WingetCreateCLI.Logging; using Microsoft.WingetCreateCLI.Properties; using Microsoft.WingetCreateCLI.Telemetry; @@ -122,7 +123,8 @@ private async Task SubmitManifest() return false; } - return await this.GitHubSubmitManifests(manifests, this.PRTitle, this.Replace, this.ReplaceVersion); + // TODO: Add Font Root Support + return await this.GitHubSubmitManifests(manifests, this.PRTitle, WingetCreateCore.Common.Constants.WingetManifestRoot, this.Replace, this.ReplaceVersion); } else if (Directory.Exists(expandedPath) && ValidateManifest(expandedPath, this.Format)) { @@ -134,7 +136,8 @@ private async Task SubmitManifest() return false; } - return await this.GitHubSubmitManifests(manifests, this.PRTitle, this.Replace, this.ReplaceVersion); + // TODO: Add Font Root Support + return await this.GitHubSubmitManifests(manifests, this.PRTitle, WingetCreateCore.Common.Constants.WingetManifestRoot, this.Replace, this.ReplaceVersion); } else { diff --git a/src/WingetCreateCLI/Commands/UpdateCommand.cs b/src/WingetCreateCLI/Commands/UpdateCommand.cs index c0aeb5ab..d519a485 100644 --- a/src/WingetCreateCLI/Commands/UpdateCommand.cs +++ b/src/WingetCreateCLI/Commands/UpdateCommand.cs @@ -278,7 +278,8 @@ await this.UpdateManifestsInteractively(initialManifests) : this.OutputDir = Directory.GetCurrentDirectory(); } - string manifestDirectoryPath = SaveManifestDirToLocalPath(updatedManifests, this.OutputDir); + // TODO: Font root support. + string manifestDirectoryPath = SaveManifestDirToLocalPath(updatedManifests, Constants.WingetManifestRoot, this.OutputDir); if (ValidateManifest(manifestDirectoryPath, this.Format)) { @@ -305,9 +306,11 @@ await this.UpdateManifestsInteractively(initialManifests) : } } + // TODO: Font root support. return await this.LoadGitHubClient(true) ? (commandEvent.IsSuccessful = await this.GitHubSubmitManifests( updatedManifests, + Constants.WingetManifestRoot, this.GetPRTitle(updatedManifests, originalManifests), this.Replace, this.ReplaceVersion)) diff --git a/src/WingetCreateCLI/Commands/UpdateLocaleCommand.cs b/src/WingetCreateCLI/Commands/UpdateLocaleCommand.cs index e57a47cc..d45e9c4b 100644 --- a/src/WingetCreateCLI/Commands/UpdateLocaleCommand.cs +++ b/src/WingetCreateCLI/Commands/UpdateLocaleCommand.cs @@ -170,7 +170,8 @@ public override async Task Execute() this.OutputDir = Directory.GetCurrentDirectory(); } - string manifestDirectoryPath = SaveManifestDirToLocalPath(originalManifests, this.OutputDir); + // TODO: Font root support. + string manifestDirectoryPath = SaveManifestDirToLocalPath(originalManifests, WingetCreateCore.Common.Constants.WingetManifestRoot, this.OutputDir); if (ValidateManifest(manifestDirectoryPath, this.Format)) { diff --git a/src/WingetCreateCLI/WingetCreateCLI.csproj b/src/WingetCreateCLI/WingetCreateCLI.csproj index c43df76f..5671f11f 100644 --- a/src/WingetCreateCLI/WingetCreateCLI.csproj +++ b/src/WingetCreateCLI/WingetCreateCLI.csproj @@ -21,9 +21,9 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive + + all + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -41,17 +41,17 @@ - @@ -69,7 +69,7 @@ - %(LinkBase)\%(Filename)%(Extension) @@ -97,11 +97,11 @@ - - - - - + + + + + diff --git a/src/WingetCreateCore/Common/Constants.cs b/src/WingetCreateCore/Common/Constants.cs index 5c898382..4a6ca81a 100644 --- a/src/WingetCreateCore/Common/Constants.cs +++ b/src/WingetCreateCore/Common/Constants.cs @@ -18,6 +18,11 @@ public static class Constants /// public const string WingetManifestRoot = "manifests"; + /// + /// Root directory of the winget-pkgs fonts repository. + /// + public const string WingetFontRoot = "fonts"; + /// /// Client Id for the WingetCreate GitHub OAuth app. /// diff --git a/src/WingetCreateCore/Common/GitHub.cs b/src/WingetCreateCore/Common/GitHub.cs index 5767ced3..3d75bef5 100644 --- a/src/WingetCreateCore/Common/GitHub.cs +++ b/src/WingetCreateCore/Common/GitHub.cs @@ -72,14 +72,15 @@ public static async Task GetGitHubAppInstallationAccessToken(string gitH /// /// Gets all app manifests in the repo. /// + /// The name of the ManifestRoot. /// A list of , each representing a single app manifest version. - public async Task> GetAppVersions() + public async Task> GetAppVersions(string manifestRoot = Constants.WingetManifestRoot) { var reference = await this.github.Git.Reference.Get(this.wingetRepoOwner, this.wingetRepo, HeadMasterRef); var tree = await this.github.Git.Tree.GetRecursive(this.wingetRepoOwner, this.wingetRepo, reference.Object.Sha); return tree.Tree - .Where(i => i.Path.StartsWith(Constants.WingetManifestRoot + "/") && i.Type.Value == TreeType.Blob) - .Select(i => new { i.Path, PathTokens = i.Path[Constants.WingetManifestRoot.Length..].Split('/') }) + .Where(i => i.Path.StartsWith(manifestRoot + "/") && i.Type.Value == TreeType.Blob) + .Select(i => new { i.Path, PathTokens = i.Path[manifestRoot.Length..].Split('/') }) .Where(i => i.PathTokens.Length >= 3) .Select(i => { @@ -136,11 +137,12 @@ public async Task> GetManifestContentAsync(string packageId, string /// /// Wrapper object for manifest object models to be submitted in the PR. /// Bool indicating whether or not to submit the PR via a fork. + /// The manifest root name. /// Optional parameter specifying the title for the pull request. /// Optional parameter specifying whether the new submission should replace an existing manifest. /// Optional parameter specifying the version of the manifest to be replaced. /// Pull request object. - public Task SubmitPullRequestAsync(Manifests manifests, bool submitToFork, string prTitle = null, bool shouldReplace = false, string replaceVersion = null) + public Task SubmitPullRequestAsync(Manifests manifests, bool submitToFork, string manifestRoot = Constants.WingetManifestRoot, string prTitle = null, bool shouldReplace = false, string replaceVersion = null) { Dictionary contents = new Dictionary(); string id; @@ -164,7 +166,7 @@ public Task SubmitPullRequestAsync(Manifests manifests, bool submit contents.Add($"{id}.locale.{manifests.DefaultLocaleManifest.PackageLocale}", manifests.DefaultLocaleManifest.ToManifestString()); } - return this.SubmitPRAsync(id, version, contents, submitToFork, prTitle, shouldReplace, replaceVersion); + return this.SubmitPRAsync(id, version, contents, submitToFork, manifestRoot, prTitle, shouldReplace, replaceVersion); } /// @@ -227,10 +229,11 @@ public async Task CheckAccess() /// Recursively searches the repository for the provided package identifer to determine if it already exists. /// /// The package identifier. + /// The manifest root name. /// The exact matching package identifier or null if no match was found. - public async Task FindPackageId(string packageId) + public async Task FindPackageId(string packageId, string manifestRoot = Constants.WingetManifestRoot) { - string path = Constants.WingetManifestRoot + '/' + $"{char.ToLowerInvariant(packageId[0])}"; + string path = manifestRoot + '/' + $"{char.ToLowerInvariant(packageId[0])}"; return await this.FindPackageIdRecursive(packageId.Split('.'), path, string.Empty, 0); } @@ -301,7 +304,7 @@ private async Task FindPackageIdRecursive(string[] packageId, string pat return null; } - private async Task SubmitPRAsync(string packageId, string version, Dictionary contents, bool submitToFork, string prTitle = null, bool shouldReplace = false, string replaceVersion = null) + private async Task SubmitPRAsync(string packageId, string version, Dictionary contents, bool submitToFork, string manifestRoot = Constants.WingetManifestRoot, string prTitle = null, bool shouldReplace = false, string replaceVersion = null) { bool createdRepo = false; Repository repo; @@ -361,7 +364,7 @@ await retryPolicy.ExecuteAsync(async () => var updatedSha = newBranch.Object.Sha; var nt = new NewTree { BaseTree = updatedSha }; - string appPath = Utils.GetAppManifestDirPath(packageId, version, '/'); + string appPath = Utils.GetAppManifestDirPath(packageId, version, manifestRoot, '/'); foreach (KeyValuePair item in contents) { @@ -414,9 +417,9 @@ await retryPolicy.ExecuteAsync(async () => } } - private async Task GetVersionDirectoryPath(string packageId, string version = null) + private async Task GetVersionDirectoryPath(string packageId, string manifestRoot = Constants.WingetManifestRoot, string version = null) { - string appPath = Utils.GetAppManifestDirPath(packageId, string.Empty, '/'); + string appPath = Utils.GetAppManifestDirPath(packageId, string.Empty, manifestRoot, '/'); var contents = await this.github.Repository.Content.GetAllContents(this.wingetRepoOwner, this.wingetRepo, appPath); string directory; diff --git a/src/WingetCreateCore/Common/PackageParser.cs b/src/WingetCreateCore/Common/PackageParser.cs index 984650c2..ba0d9728 100644 --- a/src/WingetCreateCore/Common/PackageParser.cs +++ b/src/WingetCreateCore/Common/PackageParser.cs @@ -47,6 +47,15 @@ public static class PackageParser "nullsoft", }; + private static readonly string[] FontInstallerExtensions = + [ + ".otf", // OpenType Font + ".ttf", // TrueType Font + ".fnt", // Font + ".ttc", // TrueType Font Collection + ".otc", // OpenType Font Collection + ]; + private static HttpClient httpClient = new() { DefaultRequestHeaders = @@ -380,6 +389,20 @@ public static Installer CloneInstaller(Installer installer) return JsonConvert.DeserializeObject(json); } + /// + /// Determines if a given installer path is a Font installer. + /// + /// Installer path or filename. + /// True if the installerPath is considered a font type. + public static bool IsFontInstaller(string installerPath) => FontInstallerExtensions.Any(s => installerPath.Contains(s, StringComparison.InvariantCultureIgnoreCase)); + + /// + /// Determines if a given installer path is a Font installer. + /// + /// List of installer paths. + /// True if the installerPath is considered a font type. + public static bool IsFontPackage(List installerPaths) => installerPaths.All(i => IsFontInstaller(i)); + /// /// Finds an existing installer that matches the new installer by checking the installerType and the following: /// 1. Matching based on architecture specified as an override if present. @@ -594,6 +617,22 @@ private static bool ParsePackageAndGenerateInstallerNodes(InstallerMetadata inst foreach (NestedInstallerFile nestedInstallerFile in installerMetadata.NestedInstallerFiles) { + if (IsFontInstaller(nestedInstallerFile.RelativeFilePath)) + { + // Skip adding duplicate NestedInstallerFile object. + if (baseInstaller.NestedInstallerFiles.Any(i => i.RelativeFilePath == nestedInstallerFile.RelativeFilePath)) + { + continue; + } + + baseInstaller.NestedInstallerFiles.Add(new NestedInstallerFile + { + RelativeFilePath = nestedInstallerFile.RelativeFilePath, + }); + + continue; + } + // Skip adding duplicate NestedInstallerFile object. if (baseInstaller.NestedInstallerFiles.Any(i => i.RelativeFilePath == nestedInstallerFile.RelativeFilePath && @@ -620,6 +659,14 @@ private static bool ParsePackageAndGenerateInstallerNodes(InstallerMetadata inst installerPaths.Add(packageFile); } + // If every installer path is a font this is a font package. + var isFontPackage = IsFontPackage(installerPaths); + if (isFontPackage) + { + SetFontInstallerType(baseInstaller, newInstallers); + return true; + } + Architecture? nestedArchitecture = null; bool parseMsixResult = false; @@ -885,6 +932,13 @@ private static bool ParseExeInstallerType(string path, Installer baseInstaller, } } + private static void SetFontInstallerType(Installer baseInstaller, List newInstallers) + { + SetInstallerType(baseInstaller, InstallerType.Font); + baseInstaller.Architecture = Architecture.Neutral; + newInstallers.Add(baseInstaller); + } + /// /// Checks if a MSI Installer database was generated by WiX, based on common characteristics. /// diff --git a/src/WingetCreateCore/Common/Utils.cs b/src/WingetCreateCore/Common/Utils.cs index 365e1cf5..927bba3a 100644 --- a/src/WingetCreateCore/Common/Utils.cs +++ b/src/WingetCreateCore/Common/Utils.cs @@ -36,11 +36,12 @@ public static string GetEntryAssemblyName() /// /// Package Identifier. /// Package Version. + /// The manifest root name. /// Delimiter character of the generated path. /// Full directory path where the manifests should be saved to. - public static string GetAppManifestDirPath(string packageId, string version, char pathDelimiter = '\\') + public static string GetAppManifestDirPath(string packageId, string version, string manifestRoot = Constants.WingetManifestRoot, char pathDelimiter = '\\') { - string path = Path.Combine(Constants.WingetManifestRoot, $"{char.ToLowerInvariant(packageId[0])}", packageId.Replace('.', '\\'), version); + string path = Path.Combine(manifestRoot, $"{char.ToLowerInvariant(packageId[0])}", packageId.Replace('.', '\\'), version); return pathDelimiter != '\\' ? path.Replace('\\', pathDelimiter) : path; } diff --git a/src/WingetCreateCore/Models/DefaultLocaleManifestModels.cs b/src/WingetCreateCore/Models/DefaultLocaleManifestModels.cs index 182fa6f0..71a33484 100644 --- a/src/WingetCreateCore/Models/DefaultLocaleManifestModels.cs +++ b/src/WingetCreateCore/Models/DefaultLocaleManifestModels.cs @@ -133,7 +133,7 @@ public System.Collections.Generic.IDictionary AdditionalProperti } /// - /// A representation of a multiple-file manifest representing a default app metadata in the OWC. v1.10.0 + /// A representation of a multiple-file manifest representing a default app metadata in the OWC. v1.12.0 /// [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] public partial class DefaultLocaleManifest @@ -335,7 +335,7 @@ public partial class DefaultLocaleManifest [Newtonsoft.Json.JsonProperty("ManifestVersion", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [System.ComponentModel.DataAnnotations.RegularExpression(@"^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(\.(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])){2}$")] - public string ManifestVersion { get; set; } = "1.10.0"; + public string ManifestVersion { get; set; } = "1.12.0"; diff --git a/src/WingetCreateCore/Models/InstallerManifestModels.cs b/src/WingetCreateCore/Models/InstallerManifestModels.cs index 03aaa420..c5229c24 100644 --- a/src/WingetCreateCore/Models/InstallerManifestModels.cs +++ b/src/WingetCreateCore/Models/InstallerManifestModels.cs @@ -60,6 +60,10 @@ public enum InstallerType Portable = 10, + [System.Runtime.Serialization.EnumMember(Value = @"font")] + Font = 11, + + } /// @@ -105,6 +109,10 @@ public enum NestedInstallerType Portable = 8, + [System.Runtime.Serialization.EnumMember(Value = @"font")] + Font = 9, + + } /// @@ -644,7 +652,7 @@ public System.Collections.Generic.IDictionary AdditionalProperti } /// - /// A representation of a single-file manifest representing an app installers in the OWC. v1.10.0 + /// A representation of a single-file manifest representing an app installers in the OWC. v1.12.0 /// [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] public partial class InstallerManifest @@ -813,7 +821,7 @@ public partial class InstallerManifest [Newtonsoft.Json.JsonProperty("ManifestVersion", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [System.ComponentModel.DataAnnotations.RegularExpression(@"^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(\.(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])){2}$")] - public string ManifestVersion { get; set; } = "1.10.0"; + public string ManifestVersion { get; set; } = "1.12.0"; diff --git a/src/WingetCreateCore/Models/LocaleManifestModels.cs b/src/WingetCreateCore/Models/LocaleManifestModels.cs index c7fd7dde..35f9ceeb 100644 --- a/src/WingetCreateCore/Models/LocaleManifestModels.cs +++ b/src/WingetCreateCore/Models/LocaleManifestModels.cs @@ -133,7 +133,7 @@ public System.Collections.Generic.IDictionary AdditionalProperti } /// - /// A representation of a multiple-file manifest representing app metadata in other locale in the OWC. v1.10.0 + /// A representation of a multiple-file manifest representing app metadata in other locale in the OWC. v1.12.0 /// [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] public partial class LocaleManifest @@ -324,7 +324,7 @@ public partial class LocaleManifest [Newtonsoft.Json.JsonProperty("ManifestVersion", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [System.ComponentModel.DataAnnotations.RegularExpression(@"^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(\.(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])){2}$")] - public string ManifestVersion { get; set; } = "1.10.0"; + public string ManifestVersion { get; set; } = "1.12.0"; diff --git a/src/WingetCreateCore/Models/SingletonManifestModels.cs b/src/WingetCreateCore/Models/SingletonManifestModels.cs index 1b6ee467..4317e924 100644 --- a/src/WingetCreateCore/Models/SingletonManifestModels.cs +++ b/src/WingetCreateCore/Models/SingletonManifestModels.cs @@ -183,6 +183,10 @@ public enum InstallerType Portable = 10, + [System.Runtime.Serialization.EnumMember(Value = @"font")] + Font = 11, + + } /// @@ -228,6 +232,10 @@ public enum NestedInstallerType Portable = 8, + [System.Runtime.Serialization.EnumMember(Value = @"font")] + Font = 9, + + } /// @@ -767,7 +775,7 @@ public System.Collections.Generic.IDictionary AdditionalProperti } /// - /// A representation of a single-file manifest representing an app in the OWC. v1.10.0 + /// A representation of a single-file manifest representing an app in the OWC. v1.12.0 /// [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] public partial class SingletonManifest @@ -1098,7 +1106,7 @@ public partial class SingletonManifest [Newtonsoft.Json.JsonProperty("ManifestVersion", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [System.ComponentModel.DataAnnotations.RegularExpression(@"^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(\.(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])){2}$")] - public string ManifestVersion { get; set; } = "1.10.0"; + public string ManifestVersion { get; set; } = "1.12.0"; diff --git a/src/WingetCreateCore/Models/VersionManifestModels.cs b/src/WingetCreateCore/Models/VersionManifestModels.cs index 4a4ea057..f0b8bf64 100644 --- a/src/WingetCreateCore/Models/VersionManifestModels.cs +++ b/src/WingetCreateCore/Models/VersionManifestModels.cs @@ -10,7 +10,7 @@ namespace Microsoft.WingetCreateCore.Models.Version #pragma warning disable // Disable all warnings /// - /// A representation of a multi-file manifest representing an app version in the OWC. v1.10.0 + /// A representation of a multi-file manifest representing an app version in the OWC. v1.12.0 /// [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] public partial class VersionManifest @@ -55,7 +55,7 @@ public partial class VersionManifest [Newtonsoft.Json.JsonProperty("ManifestVersion", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [System.ComponentModel.DataAnnotations.RegularExpression(@"^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(\.(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])){2}$")] - public string ManifestVersion { get; set; } = "1.10.0"; + public string ManifestVersion { get; set; } = "1.12.0"; diff --git a/src/WingetCreateTests/WingetCreateTests/UnitTests/GitHubTests.cs b/src/WingetCreateTests/WingetCreateTests/UnitTests/GitHubTests.cs index c31a72eb..d4f45dcf 100644 --- a/src/WingetCreateTests/WingetCreateTests/UnitTests/GitHubTests.cs +++ b/src/WingetCreateTests/WingetCreateTests/UnitTests/GitHubTests.cs @@ -99,11 +99,12 @@ public async Task FindMatchingPackageIdentifierAsync() public async Task GetLatestManifestAndSubmitPR() { Manifests manifests = new Manifests(); + string root = Constants.WingetManifestRoot; List latestManifest = await this.gitHub.GetManifestContentAsync(TestConstants.TestPackageIdentifier); manifests.SingletonManifest = Serialization.DeserializeFromString(latestManifest.First()); Assert.That(manifests.SingletonManifest.PackageIdentifier, Is.EqualTo(TestConstants.TestPackageIdentifier), FailedToRetrieveManifestFromId); - PullRequest pullRequest = await this.gitHub.SubmitPullRequestAsync(manifests, this.SubmitPRToFork, TestConstants.TestPRTitle); + PullRequest pullRequest = await this.gitHub.SubmitPullRequestAsync(manifests, this.SubmitPRToFork, root, TestConstants.TestPRTitle); Assert.That(TestConstants.TestPRTitle, Is.EqualTo(pullRequest.Title), TitleMismatch); await this.gitHub.ClosePullRequest(pullRequest.Number); StringAssert.StartsWith(string.Format(GitHubPullRequestBaseUrl, this.WingetPkgsTestRepoOwner, this.WingetPkgsTestRepo), pullRequest.HtmlUrl, PullRequestFailedToGenerate); diff --git a/src/WingetCreateTests/WingetCreateTests/UnitTests/UpdateCommandTests.cs b/src/WingetCreateTests/WingetCreateTests/UnitTests/UpdateCommandTests.cs index d7857d8e..4f5c7eb0 100644 --- a/src/WingetCreateTests/WingetCreateTests/UnitTests/UpdateCommandTests.cs +++ b/src/WingetCreateTests/WingetCreateTests/UnitTests/UpdateCommandTests.cs @@ -75,11 +75,12 @@ public async Task UpdateAndVerifyManifestsCreated() string packageIdentifier = "TestPublisher.SingleExe"; string version = "1.2.3.4"; + string root = Constants.WingetManifestRoot; (UpdateCommand command, var initialManifestContent) = GetUpdateCommandAndManifestData(packageIdentifier, version, this.tempPath, new[] { $"{installerUrl}" }); var updatedManifests = await command.ExecuteManifestUpdate(initialManifestContent, this.testCommandEvent); ClassicAssert.IsTrue(updatedManifests, "Command should have succeeded"); - string manifestDir = Utils.GetAppManifestDirPath(packageIdentifier, version); + string manifestDir = Utils.GetAppManifestDirPath(packageIdentifier, version, root); var updatedManifestContents = Directory.GetFiles(Path.Combine(this.tempPath, manifestDir)).Select(f => File.ReadAllText(f)); ClassicAssert.IsTrue(updatedManifestContents.Any(), "Updated manifests were not created successfully"); Manifests manifestsToValidate = Serialization.DeserializeManifestContents(updatedManifestContents); @@ -172,11 +173,12 @@ public async Task UpdateRemovesEmptyFields() { string packageId = "TestPublisher.EmptyFields"; string version = "1.2.3.4"; + string root = Constants.WingetManifestRoot; TestUtils.InitializeMockDownloads(TestConstants.TestExeInstaller); (UpdateCommand command, var initialManifestContent) = GetUpdateCommandAndManifestData(packageId, version, this.tempPath, null); bool updateExecuted = await command.ExecuteManifestUpdate(initialManifestContent, this.testCommandEvent); ClassicAssert.IsTrue(updateExecuted, "Command should have succeeded"); - string manifestDir = Utils.GetAppManifestDirPath(packageId, version); + string manifestDir = Utils.GetAppManifestDirPath(packageId, version, root); var updatedManifestContents = Directory.GetFiles(Path.Combine(this.tempPath, manifestDir)).Select(f => File.ReadAllText(f)); ClassicAssert.IsTrue(updatedManifestContents.Any(), "Updated manifests were not created successfully");