Clean up some command line arguments

This commit is contained in:
Caelan Sayler
2021-12-04 23:17:44 +00:00
parent 7290a8053a
commit ea24810d4f
4 changed files with 77 additions and 48 deletions

View File

@@ -20,7 +20,8 @@ namespace SquirrelCli
{
public string package { get; set; }
public string splashImage { get; private set; }
public string iconPath { get; private set; }
public string setupIcon { get; private set; }
//public string appIcon { get; private set; }
public string signParams { get; private set; }
public string framework { get; private set; }
public bool noDelta { get; private set; }
@@ -30,7 +31,8 @@ namespace SquirrelCli
{
Add("p=|package=", "Path to a nuget package to releasify", v => package = v);
Add("s=|splashImage=", "Image to be displayed during installation (can be jpg, png, gif, etc)", v => splashImage = v);
Add("i=|iconPath=", "Ico file that will be used where possible", v => iconPath = v);
//Add("i=|appIcon=", "ICO file that will be used for app shortcuts", v => appIcon = v);
Add("setupIcon=", "ICO file that will be used for Setup.exe", v => setupIcon = v);
Add("n=|signParams=", "Sign the installer via SignTool.exe with the parameters given", v => signParams = v);
Add("f=|framework=", "Set the required .NET framework version, e.g. net461", v => framework = v);
Add("no-delta", "Don't generate delta packages to save time", v => noDelta = true);
@@ -39,11 +41,11 @@ namespace SquirrelCli
public override void Validate()
{
IsValidFile(nameof(iconPath));
IsValidFile(nameof(setupIcon), ".ico");
IsValidFile(nameof(splashImage));
IsValidUrl(nameof(baseUrl));
IsRequired(nameof(package));
IsValidFile(nameof(package));
IsValidFile(nameof(package), ".nupkg");
}
}
@@ -53,23 +55,25 @@ namespace SquirrelCli
public string packVersion { get; private set; }
public string packAuthors { get; private set; }
public string packDirectory { get; private set; }
public bool includePdb { get; private set; }
public PackOptions()
{
Add("packName=", "desc", v => packName = v);
Add("packVersion=", "desc", v => packVersion = v);
Add("packAuthors=", "desc", v => packAuthors = v);
Add("packDirectory=", "desc", v => packDirectory = v);
Add("packName=", "The name of the package to create", v => packName = v);
Add("packVersion=", "Package version", v => packVersion = v);
Add("packAuthors=", "Comma delimited list of package authors", v => packAuthors = v);
Add("packDirectory=", "The directory with the application files that will be packaged into a release", v => packDirectory = v);
Add("includePdb", "Include the *.pdb files in the package (default: false)", v => includePdb = true);
// remove 'package' argument
Remove("package");
Remove("p");
Remove("package");
Remove("p");
}
public override void Validate()
{
IsRequired(nameof(packName), nameof(packVersion), nameof(packAuthors), nameof(packDirectory));
IsValidFile(nameof(iconPath));
IsValidFile(nameof(setupIcon), ".ico");
IsValidFile(nameof(splashImage));
IsValidUrl(nameof(baseUrl));
}
@@ -107,6 +111,7 @@ namespace SquirrelCli
public override void Validate()
{
IsRequired(nameof(url));
IsValidUrl(nameof(url));
}
}
@@ -124,6 +129,7 @@ namespace SquirrelCli
public override void Validate()
{
IsRequired(nameof(repoUrl));
IsValidUrl(nameof(repoUrl));
}
}
}

View File

@@ -25,16 +25,27 @@ namespace SquirrelCli
{
public static int Main(string[] args)
{
//var pg = new Program();
var exeName = Path.GetFileName(AssemblyRuntimeInfo.EntryExePath);
var commands = new CommandSet {
"",
$"Usage: {exeName} [verb] [--option:value]",
"Command line tool for creating and deploying Squirrel releases",
"",
"Package Authoring:",
{ "releasify", "Take an existing nuget package and turn it into a Squirrel release", new ReleasifyOptions(), Releasify },
{ "pack", "Creates a nuget package from a folder and releasifies it in a single step", new PackOptions(), Pack },
"Package Deployment / Syncing:",
{ "b2-down", "Download recent releases from BackBlaze B2", new SyncBackblazeOptions(), o => new BackblazeRepository(o).DownloadRecentPackages().Wait() },
{ "b2-up", "Upload releases to BackBlaze B2", new SyncBackblazeOptions(), o => new BackblazeRepository(o).UploadMissingPackages().Wait() },
{ "http-down", "Download recent releases from an HTTP source", new SyncHttpOptions(), o => new SimpleWebRepository(o).DownloadRecentPackages().Wait() },
//{ "http-up", "sync", new SyncHttpOptions(), o => new SimpleWebRepository(o).UploadMissingPackages().Wait() },
{ "github-down", "Download recent releases from GitHub", new SyncGithubOptions(), o => new GitHubRepository(o).DownloadRecentPackages().Wait() },
//{ "github-up", "sync", new SyncGithubOptions(), o => new GitHubRepository(o).UploadMissingPackages().Wait() },
//"",
//"Examples:",
//$" {exeName} pack ",
//$" ",
};
var logger = new ConsoleLogger();
@@ -66,9 +77,9 @@ namespace SquirrelCli
static string[] VendorDirs => new string[] {
Path.Combine(AssemblyRuntimeInfo.BaseDirectory, "..", "..", "..", "vendor")
};
static string BootstrapperPath => Utility.FindHelperExecutable("Setup.exe", throwWhenNotFound: true);
static string UpdatePath => Utility.FindHelperExecutable("Update.exe", throwWhenNotFound: true);
static string NugetPath => Utility.FindHelperExecutable("NuGet.exe", VendorDirs, throwWhenNotFound: true);
static string BootstrapperPath = Utility.FindHelperExecutable("Setup.exe", throwWhenNotFound: true);
static string UpdatePath = Utility.FindHelperExecutable("Update.exe", throwWhenNotFound: true);
static string NugetPath = Utility.FindHelperExecutable("NuGet.exe", VendorDirs, throwWhenNotFound: true);
static void Pack(PackOptions options)
{
@@ -81,17 +92,17 @@ namespace SquirrelCli
<title>{options.packName}</title>
<description>{options.packName}</description>
<authors>{options.packAuthors}</authors>
<version>0</version>
<version>{options.packVersion}</version>
</metadata>
<files>
<file src=""**"" target=""lib\app\"" exclude=""*.pdb;*.nupkg;*.vshost.*""/>
<file src=""**"" target=""lib\app\"" exclude=""{(options.includePdb ? "" : "*.pdb;")}*.nupkg;*.vshost.*""/>
</files>
</package>
".Trim();
var nuspecPath = Path.Combine(tmpDir, options.packName + ".nuspec");
File.WriteAllText(nuspecPath, nuspec);
var args = $"pack \"{nuspecPath}\" -BasePath \"{options.packDirectory}\" -OutputDirectory \"{tmpDir}\" -Version {options.packVersion}";
var args = $"pack \"{nuspecPath}\" -BasePath \"{options.packDirectory}\" -OutputDirectory \"{tmpDir}\"";
Log.Info($"Packing '{options.packDirectory}' into nupkg.");
var res = Utility.InvokeProcessAsync(NugetPath, args, CancellationToken.None).Result;
@@ -121,7 +132,7 @@ namespace SquirrelCli
var baseUrl = options.baseUrl;
var generateDeltas = !options.noDelta;
var backgroundGif = options.splashImage;
var setupIcon = options.iconPath;
var setupIcon = options.setupIcon;
// validate that the provided "frameworkVersion" is supported by Setup.exe
if (!String.IsNullOrWhiteSpace(frameworkVersion)) {
@@ -155,7 +166,7 @@ namespace SquirrelCli
var rp = new ReleasePackage(file.FullName);
rp.CreateReleasePackage(Path.Combine(di.FullName, rp.SuggestedReleaseFileName), contentsPostProcessHook: pkgPath => {
// create sub executable for all exe's in this package (except Squirrel!)
// create stub executable for all exe's in this package (except Squirrel!)
new DirectoryInfo(pkgPath).GetAllFilesRecursively()
.Where(x => x.Name.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase))
.Where(x => !x.Name.Contains("squirrel.exe", StringComparison.InvariantCultureIgnoreCase))

View File

@@ -56,13 +56,17 @@ namespace SquirrelCli
throw new OptionValidationException($"Argument '{propertyName}' is required");
}
protected virtual void IsValidFile(string propertyName)
protected virtual void IsValidFile(string propertyName, string forcedExtension = null)
{
var p = this.GetType().GetProperty(propertyName);
var path = p.GetValue(this, null) as string;
if (path != null)
if (!File.Exists(path))
if (path != null) {
if (!File.Exists(path)) {
throw new OptionValidationException($"Argument '{propertyName}': Expected file to exist at this location but no file was found");
} else if (forcedExtension != null && !Path.GetExtension(path).TrimStart('.').Equals(forcedExtension.TrimStart('.'), StringComparison.InvariantCultureIgnoreCase)) {
throw new OptionValidationException($"Argument '{propertyName}': File must be of type '{forcedExtension}'.");
}
}
}
protected virtual void IsValidUrl(string propertyName)
@@ -72,7 +76,6 @@ namespace SquirrelCli
if (val != null)
if (!Utility.IsHttpUrl(val))
throw new OptionValidationException(propertyName, "Must start with http or https and be a valid URI.");
}
public abstract void Validate();
@@ -91,6 +94,24 @@ namespace SquirrelCli
public abstract void PrintHelp();
}
internal class HelpText : CommandAction
{
public HelpText(string text)
{
Description = text;
}
public override void Execute(IEnumerable<string> args)
{
throw new NotSupportedException();
}
public override void PrintHelp()
{
Console.WriteLine(Description);
}
}
internal class CommandAction<T> : CommandAction where T : ValidatedOptionSet, new()
{
public T Options { get; }
@@ -119,7 +140,10 @@ namespace SquirrelCli
internal class CommandSet : List<CommandAction>
{
//public CommandSet() : base(StringComparer.InvariantCultureIgnoreCase) { }
public void Add(string helpText)
{
this.Add(new HelpText(helpText));
}
public void Add<T>(string command, string description, T options, Action<T> action) where T : ValidatedOptionSet, new()
{
@@ -134,7 +158,7 @@ namespace SquirrelCli
var combined = String.Join(" ", args);
CommandAction cmd = null;
foreach (var k in this.OrderByDescending(k => k.Command.Length)) {
foreach (var k in this.Where(k => !String.IsNullOrWhiteSpace(k.Command)).OrderByDescending(k => k.Command.Length)) {
if (combined.StartsWith(k.Command, StringComparison.InvariantCultureIgnoreCase)) {
cmd = k;
break;
@@ -149,31 +173,21 @@ namespace SquirrelCli
public virtual void WriteHelp()
{
var exeName = Path.GetFileName(AssemblyRuntimeInfo.EntryExePath);
Console.WriteLine($"Usage: {exeName} [command] [options]");
Console.WriteLine();
Console.WriteLine("Commands:");
var array = this.ToArray();
for (var i = 0; i < array.Length; i++) {
var c = array[i];
if (c is HelpText) {
c.PrintHelp();
continue;
}
// print command name + desc
Console.WriteLine();
Utility.ConsoleWriteWithColor(c.Command, ConsoleColor.Blue);
if (!String.IsNullOrWhiteSpace(c.Description))
Console.Write(": " + c.Description);
//Console.Write(c.Command);
//if(String.IsNullOrWhiteSpace(c.Description))
// Console.WriteLine();
//else
// Console.WriteLine(": " + c.Description);
//Console.Write(c.);
// group similar command parameters together
if (i + 1 < array.Length) {
if (c.GetType() == array[i + 1].GetType()) {
@@ -184,10 +198,6 @@ namespace SquirrelCli
Console.WriteLine();
c.PrintHelp();
//Console.WriteLine();
//c.Value.WriteOptionDescriptions();
//Console.WriteLine();
}
}
}

View File

@@ -1,5 +1,6 @@
using Mono.Options;
using System;
using System.IO;
namespace Squirrel.Update
{
@@ -30,11 +31,12 @@ namespace Squirrel.Update
private OptionSet Parse(string[] args)
{
var exeName = Path.GetFileName(AssemblyRuntimeInfo.EntryExePath);
var opts = new OptionSet() {
"Usage: Squirrel.exe command [OPTS]",
"Manages Squirrel packages",
$"Usage: {exeName} command [OPTS]",
"Manages packages and updates Squirrel applications",
"",
"Commands",
"Commands:",
{ "install=", "Install the app whose package is in the specified directory", v => { updateAction = UpdateAction.Install; target = v; } },
{ "uninstall", "Uninstall the app the same dir as Update.exe", v => updateAction = UpdateAction.Uninstall},
{ "download=", "Download the releases specified by the URL and write new results to stdout as JSON", v => { updateAction = UpdateAction.Download; target = v; } },