Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add info command to display key information #461

Merged
merged 14 commits into from
Nov 2, 2023
16 changes: 15 additions & 1 deletion doc/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ If set to true, the `telemetry.disable` setting will prevent any event from bein

## CleanUp

The `CleanUp` settings determine whether Winget-Create will handle the removal of temporary files (installer cache and logs) generated during the manifest creation process. These settings provide control over the decision to remove files or not and the frequency at which this clean up occurs.
The `CleanUp` settings determine whether Winget-Create will handle the removal of temporary files i.e., installers downloaded and logs generated during the manifest creation process. You can view the location of these files using `wingetcreate --info` command. These settings provide control over the decision to remove files or not and the frequency at which this clean up occurs.

### disable

Expand Down Expand Up @@ -60,3 +60,17 @@ The `name` setting specifies the name of the targeted GitHub repository. By defa
"name": "winget-pkgs"
}
```

## Visual

The `Visual` settings control the appearance of the Winget-Create CLI output.

### anonymizePaths

The `anonymizePaths` setting controls whether the paths of files and directories are anonymized in the Winget-Create CLI output. This means that a path such as `C:\Users\user\Documents\manifests\` will be displayed as `%USERPROFILE%\Documents\manifests` (i.e., substitute environment variables where possible). By default, this is set to `true`.

```json
"Visual": {
"anonymizePaths": true
}
```
2 changes: 1 addition & 1 deletion src/WingetCreateCLI/Commands/BaseCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ protected static string SaveManifestDirToLocalPath(
}

Console.WriteLine();
Logger.InfoLocalized(nameof(Resources.ManifestSaved_Message), fullDirPath);
Logger.InfoLocalized(nameof(Resources.ManifestSaved_Message), Common.GetPathForDisplay(fullDirPath, UserSettings.AnonymizePaths));
Console.WriteLine();

return fullDirPath;
Expand Down
36 changes: 36 additions & 0 deletions src/WingetCreateCLI/Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ namespace Microsoft.WingetCreateCLI
public static class Common
{
private const string ModuleName = "WindowsPackageManagerManifestCreator";
private const string UserProfileEnvironmentVariable = "%USERPROFILE%";
private const string LocalAppDataEnvironmentVariable = "%LOCALAPPDATA%";
private const string TempEnvironmentVariable = "%TEMP%";

private static readonly Lazy<string> AppStatePathLazy = new(() =>
{
Expand Down Expand Up @@ -61,6 +64,39 @@ public static void CleanUpFilesOlderThan(string cleanUpDirectory, int cleanUpDay
}
}

/// <summary>
/// Gets the path for display. This will anonymize the path if caller provides the appropriate flag.
/// </summary>
/// <param name="path">Path to be displayed.</param>
/// <param name="substitueEnvironmentVariables">Whether or not to substitute environment variables.</param>
/// <returns>Anonymized path or original path.</returns>
public static string GetPathForDisplay(string path, bool substitueEnvironmentVariables = true)
{
if (string.IsNullOrEmpty(path) || !substitueEnvironmentVariables)
mdanish-kh marked this conversation as resolved.
Show resolved Hide resolved
{
return path;
}

string userProfilePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
string localAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string tempPath = Path.GetTempPath();
mdanish-kh marked this conversation as resolved.
Show resolved Hide resolved

if (path.StartsWith(tempPath, StringComparison.OrdinalIgnoreCase))
{
return path.Replace(tempPath, TempEnvironmentVariable + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase);
}
else if (path.StartsWith(localAppDataPath, StringComparison.OrdinalIgnoreCase))
{
return path.Replace(localAppDataPath, LocalAppDataEnvironmentVariable, StringComparison.OrdinalIgnoreCase);
}
else if (path.StartsWith(userProfilePath, StringComparison.OrdinalIgnoreCase))
{
return path.Replace(userProfilePath, UserProfileEnvironmentVariable, StringComparison.OrdinalIgnoreCase);
}

return path;
}

private static bool IsRunningAsUwp()
{
DesktopBridge.Helpers helpers = new DesktopBridge.Helpers();
Expand Down
17 changes: 16 additions & 1 deletion src/WingetCreateCLI/Models/SettingsModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,17 @@ public partial class WindowsPackageManagerRepository
public string Name { get; set; } = "winget-pkgs";


}

/// <summary>Visual settings</summary>
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.4.3.0 (Newtonsoft.Json v11.0.0.0)")]
public partial class Visual
{
/// <summary>Controls whether paths displayed on the console are substituted with environment variables</summary>
[Newtonsoft.Json.JsonProperty("anonymizePaths", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public bool AnonymizePaths { get; set; } = true;


}

[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.4.3.0 (Newtonsoft.Json v11.0.0.0)")]
Expand All @@ -69,6 +80,10 @@ public partial class SettingsManifest
[System.ComponentModel.DataAnnotations.Required]
public WindowsPackageManagerRepository WindowsPackageManagerRepository { get; set; } = new WindowsPackageManagerRepository();

[Newtonsoft.Json.JsonProperty("Visual", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
[System.ComponentModel.DataAnnotations.Required]
public Visual Visual { get; set; } = new Visual();


}
}
}
129 changes: 100 additions & 29 deletions src/WingetCreateCLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ namespace Microsoft.WingetCreateCLI
/// </summary>
internal class Program
{
/// <summary>
/// Displays the application header and the copyright.
/// </summary>
public static void DisplayApplicationHeaderAndCopyright()
{
Console.WriteLine(string.Format(
Resources.Heading,
Utils.GetEntryAssemblyVersion()) +
Environment.NewLine +
Constants.MicrosoftCopyright);
}

private static async Task<int> Main(string[] args)
{
Logger.Initialize();
Expand All @@ -48,25 +60,46 @@ private static async Task<int> Main(string[] args)
typeof(CacheCommand),
typeof(ShowCommand),
};
var parserResult = myParser.ParseArguments(args, types);

BaseCommand command = parserResult.MapResult(c => c as BaseCommand, err => null);
var baseCommandsParserResult = myParser.ParseArguments(args, types);
BaseCommand parsedCommand = baseCommandsParserResult.MapResult(c => c as BaseCommand, err => null);

if (command == null)
if (parsedCommand == null)
{
DisplayHelp(parserResult as NotParsed<object>);
DisplayParsingErrors(parserResult as NotParsed<object>);
// In case of unsuccessful parsing, check if user tried to run a valid command.
bool isBaseCommand = baseCommandsParserResult.TypeInfo.Current.BaseType.Equals(typeof(BaseCommand));

/* Parse root options.
* Adding '--help' is a workaround to force parser to display the options help text when no arguments are passed.
* This makes rootOptionsParserResult to be a NotParsed object which makes HelpText.AutoBuild print the correct help text.
* This is done since the parser does not print the correct help text on a successful parse.
*/
ParserResult<RootOptions> rootOptionsParserResult = myParser.ParseArguments<RootOptions>(
mdanish-kh marked this conversation as resolved.
Show resolved Hide resolved
args.Length == 0 ? new string[] { "--help" } : args);

if (!isBaseCommand)
{
rootOptionsParserResult.WithParsed(RootOptions.ParseRootOptions);

if (rootOptionsParserResult.Tag == ParserResultType.Parsed)
{
return 0;
}
mdanish-kh marked this conversation as resolved.
Show resolved Hide resolved
}

DisplayHelp(baseCommandsParserResult as NotParsed<object>, isBaseCommand ? null : rootOptionsParserResult as NotParsed<RootOptions>);
DisplayParsingErrors(baseCommandsParserResult as NotParsed<object>);
return args.Any() ? 1 : 0;
}

if (command is not SettingsCommand && command is not CacheCommand)
if (parsedCommand is not SettingsCommand && parsedCommand is not CacheCommand)
{
// Do not load github client for settings or cache command.
if (await command.LoadGitHubClient())
if (await parsedCommand.LoadGitHubClient())
{
try
{
string latestVersion = await command.GitHubClient.GetLatestRelease();
string latestVersion = await parsedCommand.GitHubClient.GetLatestRelease();
string trimmedVersion = latestVersion.TrimStart('v').Split('-').First();
if (trimmedVersion != Utils.GetEntryAssemblyVersion())
{
Expand All @@ -84,7 +117,7 @@ private static async Task<int> Main(string[] args)
else
{
// Do not block creating a new manifest if loading the GitHub client fails. InstallerURL could point to a local network.
if (command is not NewCommand)
if (parsedCommand is not NewCommand)
{
return 1;
}
Expand All @@ -94,7 +127,7 @@ private static async Task<int> Main(string[] args)
try
{
WingetCreateCore.Serialization.ProducedBy = string.Join(" ", Constants.ProgramName, Utils.GetEntryAssemblyVersion());
return await command.Execute() ? 0 : 1;
return await parsedCommand.Execute() ? 0 : 1;
}
catch (Exception ex)
{
Expand All @@ -118,28 +151,66 @@ private static async Task<int> Main(string[] args)
}
}

private static void DisplayHelp(NotParsed<object> result)
private static void DisplayHelp(NotParsed<object> baseCommandsParserResult, ParserResult<RootOptions> rootOptionsParserResult)
{
DisplayApplicationHeaderAndCopyright();
DisplayCommandsHelpText(baseCommandsParserResult);
if (rootOptionsParserResult != null)
{
DisplayRootOptionsHelpText(rootOptionsParserResult);
}

DisplayFooter();
}

private static void DisplayCommandsHelpText(NotParsed<object> result)
{
var helpText = HelpText.AutoBuild(
result,
h =>
{
h.AddDashesToOption = true;
h.AdditionalNewLineAfterOption = false;
h.Heading = string.Format(Resources.Heading, Utils.GetEntryAssemblyVersion()) + Environment.NewLine;
h.Copyright = Constants.MicrosoftCopyright;
h.AddNewLineBetweenHelpSections = true;
h.AddPreOptionsLine(Resources.AppDescription_HelpText);
h.AddPostOptionsLines(new string[] { Resources.MoreHelp_HelpText, Resources.PrivacyStatement_HelpText });
h.MaximumDisplayWidth = 100;
h.AutoHelp = false;
h.AutoVersion = false;
return h;
},
e => e,
verbsIndex: true);
result,
h =>
{
h.AddDashesToOption = true;
h.AdditionalNewLineAfterOption = false;
h.Heading = string.Empty;
h.Copyright = string.Empty;
h.AddNewLineBetweenHelpSections = true;
h.AddPreOptionsLine(Resources.AppDescription_HelpText);
h.AddPreOptionsLine(Environment.NewLine);
h.AddPreOptionsLine(Resources.CommandsAvailable_Message);
h.MaximumDisplayWidth = 100;
h.AutoHelp = false;
h.AutoVersion = false;
return h;
},
e => e,
verbsIndex: true);
Console.WriteLine(helpText);
}

private static void DisplayRootOptionsHelpText(ParserResult<RootOptions> result)
{
var helpText = HelpText.AutoBuild(
result,
h =>
{
h.AddDashesToOption = true;
h.AdditionalNewLineAfterOption = false;
h.Heading = Resources.OptionsAvailable_Message;
h.Copyright = string.Empty;
h.AddNewLineBetweenHelpSections = false;
h.MaximumDisplayWidth = 100;
h.AutoHelp = false;
h.AutoVersion = false;
return h;
},
e => e);
Console.WriteLine(helpText);
Console.WriteLine();
}

private static void DisplayFooter()
{
Console.WriteLine(Resources.MoreHelp_HelpText);
Console.WriteLine(Resources.PrivacyStatement_HelpText);
}

private static void DisplayParsingErrors<T>(NotParsed<T> result)
Expand Down
Loading