Skip to content
Draft
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
60 changes: 54 additions & 6 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();
var isFontPackage = false;

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

int extractedFilesCount = extractedFiles.Count();

// Font packages have a single installer entry with many nested installer files.
isFontPackage = PackageParser.IsFontPackage(extractedFiles);

List<string> selectedInstallers;

if (extractedFilesCount == 0)
Expand All @@ -180,23 +199,51 @@ public override async Task<bool> 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<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
{
Expand Down Expand Up @@ -282,7 +329,8 @@ public override async Task<bool> 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))
{
Expand Down Expand Up @@ -494,13 +542,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 or font
/// 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(); //// || (i.NestedInstallerType == NestedInstallerType.Font)).ToList();
var mergeableInstallersList = nestedPortableInstallers.GroupBy(i => i.Architecture + i.InstallerSha256).ToList();
foreach (var installers in mergeableInstallersList)
{
Expand Down
3 changes: 2 additions & 1 deletion src/WingetCreateCLI/Commands/NewLocaleCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,8 @@ 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.
string manifestDirectoryPath = SaveManifestDirToLocalPath(originalManifests, Constants.WingetManifestRoot, this.OutputDir);

if (ValidateManifest(manifestDirectoryPath, this.Format))
{
Expand Down
7 changes: 5 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,8 @@ private async Task<bool> 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))
{
Expand All @@ -140,7 +142,8 @@ private async Task<bool> 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
{
Expand Down
5 changes: 4 additions & 1 deletion src/WingetCreateCLI/Commands/UpdateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,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))
{
Expand All @@ -314,9 +315,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))
Expand Down
3 changes: 2 additions & 1 deletion src/WingetCreateCLI/Commands/UpdateLocaleCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@ public override async Task<bool> 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))
{
Expand Down
40 changes: 20 additions & 20 deletions src/WingetCreateCLI/WingetCreateCLI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="DesktopBridge.Helpers" Version="1.2.2" />
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.183">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.183">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NSwag.MSBuild" Version="14.0.3">
<PrivateAssets>all</PrivateAssets>
Expand All @@ -41,17 +41,17 @@
<ProjectReference Include="..\WingetCreateCore\WingetCreateCore.csproj" />
</ItemGroup>

<!--This is to workaround a similar issue as to what's
described at https://github.com/dotnet/runtime/issues/3807. When the wapproj is published, the native
PDBs in its dependencies are declared in the deps.json file, but the PDBs themselves are stripped away
during the build. It'll build without complaint, but at runtime we get a message like:
Message: Error:
An assembly specified in the application dependencies manifest (WingetCreateCLI.deps.json) was not found:
package: 'Microsoft.WindowsPackageManager.Utils', version: '0.2.2'
path: 'runtimes/win-x64/native/WinGetUtil.pdb'
This modifies the inputs to GenerateBuildDependencyFile to remove Wingetutil.pdb from the deps.json file when it's generated.
<!--This is to workaround a similar issue as to what's
described at https://github.com/dotnet/runtime/issues/3807. When the wapproj is published, the native
PDBs in its dependencies are declared in the deps.json file, but the PDBs themselves are stripped away
during the build. It'll build without complaint, but at runtime we get a message like:

Message: Error:
An assembly specified in the application dependencies manifest (WingetCreateCLI.deps.json) was not found:
package: 'Microsoft.WindowsPackageManager.Utils', version: '0.2.2'
path: 'runtimes/win-x64/native/WinGetUtil.pdb'

This modifies the inputs to GenerateBuildDependencyFile to remove Wingetutil.pdb from the deps.json file when it's generated.
-->
<Target Name="StripNativePDBFromDepsJson" BeforeTargets="GenerateBuildDependencyFile">
<ItemGroup>
Expand All @@ -69,7 +69,7 @@
</ItemGroup>

<ItemGroup>
<!-- The localized resources are dropped in \Localization\Resources as part of the patch file from TouchDown. We can't simply Include them, as they must appear to be under the
<!-- The localized resources are dropped in \Localization\Resources as part of the patch file from TouchDown. We can't simply Include them, as they must appear to be under the
Properties directory to be properly included. We can fake this by using the <Link> tag which includes them virtually under specified directory -->
<EmbeddedResource Include="..\..\Localization\Resources\**\*.resx" LinkBase="Properties">
<Link>%(LinkBase)\%(Filename)%(Extension)</Link>
Expand Down Expand Up @@ -97,11 +97,11 @@

<ItemGroup>
<SettingSchema Include="$(ProjectDir)\Schemas\settings.schema.0.1.json" ModelName="Settings" />
</ItemGroup>
<ItemGroup>
<Folder Include="Models\" />
</ItemGroup>
</ItemGroup>

<ItemGroup>
<Folder Include="Models\" />
</ItemGroup>

<!--Generate settings manifest-->
<Target Name="PreBuild" BeforeTargets="PreBuildEvent" Inputs="@(SettingSchema)" Outputs="@(SettingSchema -> '$(ProjectDir)Models\%(ModelName)Model.cs')">
Expand Down
5 changes: 5 additions & 0 deletions src/WingetCreateCore/Common/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ public static class Constants
/// </summary>
public const string WingetManifestRoot = "manifests";

/// <summary>
/// Root directory of the winget-pkgs fonts repository.
/// </summary>
public const string WingetFontRoot = "fonts";

/// <summary>
/// Client Id for the WingetCreate GitHub OAuth app.
/// </summary>
Expand Down
Loading