Skip to content

Commit

Permalink
Add support for creating and updating locales (#480)
Browse files Browse the repository at this point in the history
  • Loading branch information
mdanish-kh committed Dec 15, 2023
1 parent 9fd1078 commit 445ffa2
Show file tree
Hide file tree
Showing 20 changed files with 1,609 additions and 81 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ choco install wingetcreate
| ------- | ----------- |
| [New](doc/new.md) | Command for creating a new manifest from scratch |
| [Update](doc/update.md) | Command for updating an existing manifest |
| [New-Locale](doc/new-locale.md) | Command for creating a new locale for an existing manifest |
| [Update-Locale](doc/update-locale.md) | Command for updating a locale for an existing manifest |
| [Submit](doc/submit.md) | Command for submitting an existing PR |
| [Show](doc/show.md) | Command for displaying existing manifests |
| [Token](doc/token.md) | Command for managing cached GitHub personal access tokens |
Expand Down
33 changes: 33 additions & 0 deletions doc/new-locale.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# new-locale command (Winget-Create)

The **new-locale** command of the [Winget-Create](../README.md) tool is designed to create a new locale for an existing manifest from the [Windows Package Manager repo](https://docs.microsoft.com/windows/package-manager/). This command offers an interactive flow, prompting user for a set of locale fields and then generating a new locale manifest.

## Usage

Add a new locale for the latest version of a package:

`wingetcreate.exe new-locale <PackageIdentifier> --token <GitHubPersonalAccessToken>`

Add a new locale for a specific version of a package:

`wingetcreate.exe new-locale <PackageIdentifier> --token <GitHubPersonalAccessToken> --version <Version>`

Create a new locale and save the generated manifests to a specified directory:

`wingetcreate.exe new-locale <PackageIdentifier> --out <OutputDirectory> --token <GitHubPersonalAccessToken> --version <Version>`

## Arguments

The following arguments are available:

| Argument | Description |
|--------------|-------------|
| **id** | Required. Package identifier used to lookup the existing manifest on the Windows Package Manager repo.
| **-v, --version** | The version of the package to add a new locale for. Default is the latest version.
| **-l, --locale** | The package locale to create a new manifest for. If not provided, the tool will prompt you for this value.
| **-r, --reference-locale** | Existing locale manifest to be used as reference for default values. If not provided, the default locale manifest will be used.
| **-o, --out** | The output directory where the newly created manifests will be saved locally.
| **-t,--token** | GitHub personal access token used for direct submission to the Windows Package Manager repo |
| **-?, --help** | Gets additional help on this command |

Instructions on setting up GitHub Token for Winget-Create can be found [here](../README.md#github-personal-access-token-classic-permissions).
32 changes: 32 additions & 0 deletions doc/update-locale.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# update-locale command (Winget-Create)

The **update-locale** command of the [Winget-Create](../README.md) tool is designed to update existing locales for a manifest from the [Windows Package Manager repo](https://docs.microsoft.com/windows/package-manager/). This command offers an interactive flow, prompting user for a set of locale fields and then generating a new manifest for submission.

## Usage

Update existing locales for the latest version of a package:

`wingetcreate.exe update-locale <PackageIdentifier> --token <GitHubPersonalAccessToken>`

Update existing locales for a specific version of a package:

`wingetcreate.exe update-locale <PackageIdentifier> --token <GitHubPersonalAccessToken> --version <Version>`

Update existing locale and save the generated manifests to a specified directory:

`wingetcreate.exe update-locale <PackageIdentifier> --out <OutputDirectory> --token <GitHubPersonalAccessToken> --version <Version>`

## Arguments

The following arguments are available:

| Argument | Description |
|--------------|-------------|
| **id** | Required. Package identifier used to lookup the existing manifest on the Windows Package Manager repo.
| **-v, --version** | The version of the package to update the locale for. Default is the latest version.
| **-l, --locale** | The package locale to update the manifest for. If not provided, the tool will prompt you a list of existing locales to choose from.
| **-o, --out** | The output directory where the newly created manifests will be saved locally.
| **-t,--token** | GitHub personal access token used for direct submission to the Windows Package Manager repo |
| **-?, --help** | Gets additional help on this command |

Instructions on setting up GitHub Token for Winget-Create can be found [here](../README.md#github-personal-access-token-classic-permissions).
87 changes: 87 additions & 0 deletions src/WingetCreateCLI/Commands/BaseCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ namespace Microsoft.WingetCreateCLI.Commands
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.WingetCreateCLI.Logging;
using Microsoft.WingetCreateCLI.Properties;
Expand All @@ -23,8 +25,10 @@ namespace Microsoft.WingetCreateCLI.Commands
using Microsoft.WingetCreateCore.Models.Installer;
using Microsoft.WingetCreateCore.Models.Locale;
using Microsoft.WingetCreateCore.Models.Version;
using Newtonsoft.Json;
using Octokit;
using RestSharp;
using Sharprompt;

/// <summary>
/// Abstract base command class that all commands inherit from.
Expand Down Expand Up @@ -219,6 +223,12 @@ protected static bool ValidateManifestsInTempDir(Manifests manifests)
File.WriteAllText(Path.Combine(randomDirPath, installerManifestFileName), manifests.InstallerManifest.ToYaml());
File.WriteAllText(Path.Combine(randomDirPath, defaultLocaleManifestFileName), manifests.DefaultLocaleManifest.ToYaml());

foreach (LocaleManifest localeManifest in manifests.LocaleManifests)
{
string localeManifestFileName = Manifests.GetFileName(localeManifest);
File.WriteAllText(Path.Combine(randomDirPath, localeManifestFileName), localeManifest.ToYaml());
}

bool result = ValidateManifest(randomDirPath);
Directory.Delete(randomDirPath, true);
return result;
Expand Down Expand Up @@ -515,6 +525,83 @@ protected static void ShiftInstallerFieldsToRootLevel(InstallerManifest installe
}
}

/// <summary>
/// Prompts user to enter values for the optional properties of the manifest.
/// </summary>
/// <typeparam name="T">Type of the manifest.</typeparam>
/// <param name="manifest">Object model of the manifest.</param>
/// <param name="optionalPropertiesNames">Optional parameter to specify the list of property names to be prompted for.</param>
protected static void PromptOptionalProperties<T>(T manifest, List<string> optionalPropertiesNames = null)
{
List<PropertyInfo> optionalProperties;
if (optionalPropertiesNames == null)
{
optionalProperties = manifest.GetType().GetProperties().ToList().Where(p =>
p.GetCustomAttribute<RequiredAttribute>() == null &&
p.GetCustomAttribute<JsonPropertyAttribute>() != null).ToList();
}
else
{
optionalProperties = manifest.GetType().GetProperties().Where(p => optionalPropertiesNames.Contains(p.Name)).ToList();
}

foreach (var property in optionalProperties)
{
Type type = property.PropertyType;
if (type.IsEnumerable())
{
Type elementType = type.GetGenericArguments().SingleOrDefault();
if (elementType.IsNonStringClassType() && !Prompt.Confirm(string.Format(Resources.EditObjectTypeField_Message, property.Name)))
{
continue;
}
}

PromptHelper.PromptPropertyAndSetValue(manifest, property.Name, property.GetValue(manifest));
Logger.Trace($"Property [{property.Name}] set to the value [{property.GetValue(manifest)}]");
}
}

/// <summary>
/// Displays the preview of the default locale manifest to the console.
/// </summary>
/// <param name="defaultLocaleManifest">Object model of the default locale manifest.</param>
protected static void DisplayDefaultLocaleManifest(DefaultLocaleManifest defaultLocaleManifest)
{
Logger.InfoLocalized(nameof(Resources.DefaultLocaleManifest_Message), defaultLocaleManifest.PackageLocale);
Console.WriteLine(defaultLocaleManifest.ToYaml(true));
}

/// <summary>
/// Displays the preview of all the locale manifests to the console.
/// </summary>
/// <param name="localeManifests">List of locale manifest object models.</param>
protected static void DisplayLocaleManifests(List<LocaleManifest> localeManifests)
{
foreach (var localeManifest in localeManifests)
{
Logger.InfoLocalized(nameof(Resources.LocaleManifest_Message), localeManifest.PackageLocale);
Console.WriteLine(localeManifest.ToYaml(true));
}
}

/// <summary>
/// Ensures that the manifestVersion is consistent across all manifest object models.
/// </summary>
/// <param name="manifests">Manifests object model.</param>
protected static void EnsureManifestVersionConsistency(Manifests manifests)
{
string latestManifestVersion = new VersionManifest().ManifestVersion;
manifests.VersionManifest.ManifestVersion = latestManifestVersion;
manifests.DefaultLocaleManifest.ManifestVersion = latestManifestVersion;
manifests.InstallerManifest.ManifestVersion = latestManifestVersion;

foreach (var localeManifest in manifests.LocaleManifests)
{
localeManifest.ManifestVersion = latestManifestVersion;
}
}

/// <summary>
/// Launches the GitHub OAuth flow and obtains a GitHub token.
/// </summary>
Expand Down
33 changes: 2 additions & 31 deletions src/WingetCreateCLI/Commands/NewCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,6 @@ namespace Microsoft.WingetCreateCLI.Commands
[Verb("new", HelpText = "NewCommand_HelpText", ResourceType = typeof(Resources))]
public class NewCommand : BaseCommand
{
/// <summary>
/// The url path to the manifest documentation site.
/// </summary>
private const string ManifestDocumentationUrl = "https://aka.ms/winget-manifest-schema";

/// <summary>
/// Installer types for which we can trust that the detected architecture is correct, so don't need to prompt the user to confirm.
/// </summary>
Expand Down Expand Up @@ -210,9 +205,9 @@ public override async Task<bool> Execute()
Console.WriteLine();
Console.WriteLine(Resources.NewCommand_Header);
Console.WriteLine();
Logger.InfoLocalized(nameof(Resources.ManifestDocumentation_HelpText), ManifestDocumentationUrl);
Logger.InfoLocalized(nameof(Resources.ManifestDocumentation_HelpText), Constants.ManifestDocumentationUrl);
Console.WriteLine();
Console.WriteLine(Resources.NewCommand_Description);
Console.WriteLine(Resources.NewCommand_PrePrompt_Header);
Console.WriteLine();

Logger.DebugLocalized(nameof(Resources.EnterFollowingFields_Message));
Expand Down Expand Up @@ -338,30 +333,6 @@ private static void PromptRequiredProperties<T>(T manifest, VersionManifest vers
}
}

private static void PromptOptionalProperties<T>(T manifest)
{
var properties = manifest.GetType().GetProperties().ToList();
var optionalProperties = properties.Where(p =>
p.GetCustomAttribute<RequiredAttribute>() == null &&
p.GetCustomAttribute<JsonPropertyAttribute>() != null).ToList();

foreach (var property in optionalProperties)
{
Type type = property.PropertyType;
if (type.IsEnumerable())
{
Type elementType = type.GetGenericArguments().SingleOrDefault();
if (elementType.IsNonStringClassType() && !Prompt.Confirm(string.Format(Resources.EditObjectTypeField_Message, property.Name)))
{
continue;
}
}

PromptHelper.PromptPropertyAndSetValue(manifest, property.Name, property.GetValue(manifest));
Logger.Trace($"Property [{property.Name}] set to the value [{property.GetValue(manifest)}]");
}
}

private static void PromptInstallerProperties<T>(T manifest, PropertyInfo property)
{
List<Installer> installers = new List<Installer>((ICollection<Installer>)property.GetValue(manifest));
Expand Down
Loading

0 comments on commit 445ffa2

Please sign in to comment.