Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/WingetCreateCLI/Commands/BaseCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,12 @@ public async Task<bool> LoadGitHubClient(bool requireToken = false)
/// Creates a formatted directory of manifest files from the manifest object models and saves the directory to a local path.
/// </summary>
/// <param name="manifests">Wrapper object for manifest object models.</param>
/// <param name="manifestRoot">Manifest root name.</param>
/// <param name="outputDir">Output directory where the manifests are saved locally.</param>
/// <returns>Path to manifest directory.</returns>
protected static string SaveManifestDirToLocalPath(
Manifests manifests,
string manifestRoot,
string outputDir)
{
VersionManifest versionManifest = manifests.VersionManifest;
Expand All @@ -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
Expand Down Expand Up @@ -739,11 +741,12 @@ protected async Task<bool> CheckGitHubTokenAndSetClient()
/// Submits a pull request with multifile manifests using the user's GitHub access token.
/// </summary>
/// <param name="manifests">Wrapper object for manifest object models to be submitted.</param>
/// <param name="manifestRoot">Manifest root name.</param>
/// <param name="prTitle">Optional parameter specifying the title for the pull request.</param>
/// <param name="shouldReplace">Optional parameter specifying whether the new submission should replace an existing manifest.</param>
/// <param name="replaceVersion">Optional parameter specifying the version of the manifest to be replaced.</param>
/// <returns>A <see cref="Task"/> representing the success of the asynchronous operation.</returns>
protected async Task<bool> GitHubSubmitManifests(Manifests manifests, string prTitle = null, bool shouldReplace = false, string replaceVersion = null)
protected async Task<bool> 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 &&
Expand All @@ -765,7 +768,7 @@ protected async Task<bool> GitHubSubmitManifests(Manifests manifests, string prT

try
{
Octokit.PullRequest pullRequest = await this.GitHubClient.SubmitPullRequestAsync(manifests, this.SubmitPRToFork, prTitle, shouldReplace, replaceVersion);
Octokit.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);
Expand Down
97 changes: 90 additions & 7 deletions src/WingetCreateCLI/Commands/NewCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
Expand All @@ -41,7 +42,20 @@ public class NewCommand : BaseCommand
/// <summary>
/// Installer type file extensions that are supported.
/// </summary>
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
];

/// <summary>
/// Gets the usage examples for the New command.
Expand Down Expand Up @@ -117,6 +131,7 @@ public override async Task<bool> Execute()
Prompt.Symbols.Prompt = new Symbol(string.Empty, string.Empty);

Manifests manifests = new Manifests();
PackageParser.ManifestRootType manifestRootType = PackageParser.ManifestRootType.Unknown;

if (!this.InstallerUrls.Any())
{
Expand Down Expand Up @@ -169,6 +184,29 @@ public override async Task<bool> Execute()
.ToList();

int extractedFilesCount = extractedFiles.Count();

var rootTypeForFiles = PackageParser.GetManifestRootTypeForInstallerPaths(extractedFiles);
var isFontPackage = rootTypeForFiles == PackageParser.ManifestRootType.Fonts;

// Set the root type if it is unknown.
if (manifestRootType == PackageParser.ManifestRootType.Unknown)
{
manifestRootType = rootTypeForFiles;
}

// Check for installer type mismatches or mixed installers.
if ((manifestRootType != rootTypeForFiles) || (manifestRootType == PackageParser.ManifestRootType.Unknown))
{
// Mismatched root and installer types is a WinGet-Pkgs policy, not an invalid manifest.
Logger.WarnLocalized(nameof(Resources.MixedInstallerRootTypes_ErrorMessage));
}

// If the root type is still unknown, it means a mixed package. We will assume manifests.
if (manifestRootType == PackageParser.ManifestRootType.Unknown)
{
manifestRootType = PackageParser.ManifestRootType.Manifests;
}

List<string> selectedInstallers;

if (extractedFilesCount == 0)
Expand All @@ -180,26 +218,70 @@ public override async Task<bool> Execute()
{
selectedInstallers = extractedFiles;
}
else if (isFontPackage)
{
// If this is a font package, every installer is intended to be installed.
Comment thread
dkbennett marked this conversation as resolved.
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<NestedInstallerFile> nestedInstallerFiles = [];
foreach (var fontFile in selectedInstallers)
{
nestedInstallerFiles.Add(new NestedInstallerFile { RelativeFilePath = fontFile });
}

installerUpdateList.Add(
new InstallerMetadata
{
InstallerUrl = installerUrl,
PackageFile = packageFile,
NestedInstallerFiles = new List<NestedInstallerFile> { 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<NestedInstallerFile> { new NestedInstallerFile { RelativeFilePath = installer } },
IsZipFile = true,
ExtractedDirectory = extractDirectory,
});
}
}
}
else
else // Not a Zip package archive.
{
// Set the manifest root type. There is only one file here so it can only be Font or Manifests.
var rootTypeForInstaller = PackageParser.GetManifestRootTypeForInstallerPaths([packageFile]);

// Set the root type if it is unknown.
if (manifestRootType == PackageParser.ManifestRootType.Unknown)
{
manifestRootType = rootTypeForInstaller;
}

// Check for root type mismatches.
if (manifestRootType != rootTypeForInstaller)
{
// Mismatched root and installer types is a WinGet-Pkgs policy, not an invalid manifest.
Logger.WarnLocalized(nameof(Resources.MixedInstallerRootTypes_ErrorMessage));
}

installerUpdateList.Add(new InstallerMetadata { InstallerUrl = installerUrl, PackageFile = packageFile });
}
}
Expand Down Expand Up @@ -282,7 +364,8 @@ public override async Task<bool> Execute()
this.OutputDir = Directory.GetCurrentDirectory();
}

SaveManifestDirToLocalPath(manifests, this.OutputDir);
var manifestRoot = manifestRootType == PackageParser.ManifestRootType.Fonts ? Constants.WingetFontRoot : Constants.WingetManifestRoot;
SaveManifestDirToLocalPath(manifests, manifestRoot, this.OutputDir);

if (isManifestValid && Prompt.Confirm(Resources.ConfirmGitHubSubmitManifest_Message))
{
Expand Down Expand Up @@ -494,13 +577,13 @@ private static void PromptForPortableFieldsIfApplicable(Installer installer)

/// <summary>
/// Merge nested installer files into a single installer if:
/// 1. Matching installers have NestedInstallerType: portable.
/// 1. Matching installers have NestedInstallerType: portable
/// 2. Matching installers have the same architecture.
/// 3. Matching installers have the same hash.
/// </summary>
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();
var mergeableInstallersList = nestedPortableInstallers.GroupBy(i => i.Architecture + i.InstallerSha256).ToList();
foreach (var installers in mergeableInstallersList)
{
Expand Down
5 changes: 4 additions & 1 deletion src/WingetCreateCLI/Commands/NewLocaleCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,10 @@ public override async Task<bool> Execute()
this.OutputDir = Directory.GetCurrentDirectory();
}

string manifestDirectoryPath = SaveManifestDirToLocalPath(originalManifests, this.OutputDir);
// TODO: Need to discern font root manifests. Assume default root for now.
Comment thread
dkbennett marked this conversation as resolved.
// All of this locale code is generated assuming 'manifests' root, and updating it to support fonts
// would require significant restructuring. See issue https://github.com/microsoft/winget-create/issues/647
string manifestDirectoryPath = SaveManifestDirToLocalPath(originalManifests, Constants.WingetManifestRoot, this.OutputDir);

if (ValidateManifest(manifestDirectoryPath, this.Format))
{
Expand Down
9 changes: 7 additions & 2 deletions src/WingetCreateCLI/Commands/SubmitCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -128,7 +129,9 @@ private async Task<bool> SubmitManifest()
return false;
}

return await this.GitHubSubmitManifests(manifests, this.PRTitle, this.Replace, this.ReplaceVersion);
// TODO: Add Font Root Support
Comment thread
AmelBawa-msft marked this conversation as resolved.
// See issue: See issue https://github.com/microsoft/winget-create/issues/647
return await this.GitHubSubmitManifests(manifests, this.PRTitle, WingetCreateCore.Common.Constants.WingetManifestRoot, this.Replace, this.ReplaceVersion);
}
else if (Directory.Exists(expandedPath) && ValidateManifest(expandedPath, this.Format))
{
Expand All @@ -140,7 +143,9 @@ private async Task<bool> SubmitManifest()
return false;
}

return await this.GitHubSubmitManifests(manifests, this.PRTitle, this.Replace, this.ReplaceVersion);
// TODO: Add Font Root Support
// See issue: See issue https://github.com/microsoft/winget-create/issues/647
return await this.GitHubSubmitManifests(manifests, this.PRTitle, WingetCreateCore.Common.Constants.WingetManifestRoot, this.Replace, this.ReplaceVersion);
}
else
{
Expand Down
7 changes: 6 additions & 1 deletion src/WingetCreateCLI/Commands/UpdateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,9 @@ await this.UpdateManifestsInteractively(initialManifests) :
this.OutputDir = Directory.GetCurrentDirectory();
}

string manifestDirectoryPath = SaveManifestDirToLocalPath(updatedManifests, this.OutputDir);
// TODO: Font root support.
// See issue: See issue https://github.com/microsoft/winget-create/issues/647
string manifestDirectoryPath = SaveManifestDirToLocalPath(updatedManifests, Constants.WingetManifestRoot, this.OutputDir);

if (ValidateManifest(manifestDirectoryPath, this.Format))
{
Expand All @@ -314,9 +316,12 @@ await this.UpdateManifestsInteractively(initialManifests) :
}
}

// TODO: Font root support.
// See issue: See issue https://github.com/microsoft/winget-create/issues/647
return await this.LoadGitHubClient(true)
? (commandEvent.IsSuccessful = await this.GitHubSubmitManifests(
updatedManifests,
Constants.WingetManifestRoot,
this.GetPRTitle(updatedManifests, originalManifests),
this.Replace,
this.ReplaceVersion))
Expand Down
4 changes: 3 additions & 1 deletion src/WingetCreateCLI/Commands/UpdateLocaleCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,9 @@ public override async Task<bool> Execute()
this.OutputDir = Directory.GetCurrentDirectory();
}

string manifestDirectoryPath = SaveManifestDirToLocalPath(originalManifests, this.OutputDir);
// TODO: Font root support.
// See issue: See issue https://github.com/microsoft/winget-create/issues/647
string manifestDirectoryPath = SaveManifestDirToLocalPath(originalManifests, WingetCreateCore.Common.Constants.WingetManifestRoot, this.OutputDir);

if (ValidateManifest(manifestDirectoryPath, this.Format))
{
Expand Down
9 changes: 9 additions & 0 deletions src/WingetCreateCLI/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/WingetCreateCLI/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1483,4 +1483,7 @@ Warning: Using this argument may result in the token being logged. Consider an a
<data name="NoOpenPRInBrowser_HelpText" xml:space="preserve">
<value>Boolean value that controls whether the pull request should not be open in the browser on submission. Default is false.</value>
</data>
<data name="MixedInstallerRootTypes_ErrorMessage" xml:space="preserve">
<value>Found mixed font and non-font installer types in the manifest. This is not a supported configuration and the manifest should be edited to contain only font or non-font installers before submission.</value>
</data>
</root>
Loading