126 lines
4.1 KiB
C#
126 lines
4.1 KiB
C#
namespace HanaToolbox.Cli;
|
|
|
|
/// <summary>
|
|
/// Parsed result from the CLI argument array.
|
|
/// Lightweight, AOT-safe, zero external dependencies.
|
|
/// </summary>
|
|
public sealed class CliArgs
|
|
{
|
|
public string Command { get; init; } = string.Empty; // e.g. "backup", "cron"
|
|
public string SubCommand { get; init; } = string.Empty; // e.g. "setup" for "cron setup"
|
|
public List<string> Positional { get; init; } = []; // non-flag arguments
|
|
|
|
public bool Verbose { get; init; }
|
|
public string Sid { get; init; } = string.Empty;
|
|
public bool Compress { get; init; }
|
|
public int Threads { get; init; }
|
|
public bool Replace { get; init; }
|
|
|
|
/// <summary>
|
|
/// Parses raw args into a CliArgs instance.
|
|
///
|
|
/// Global options: -v | --verbose
|
|
/// --sid <SID>
|
|
///
|
|
/// Command-local options are also parsed here for simplicity (they are
|
|
/// silently ignored when not applicable to the active command).
|
|
///
|
|
/// Usage examples:
|
|
/// hanatoolbox backup --verbose --sid NDB
|
|
/// hanatoolbox export MYSCHEMA /hana/backup -c -t 4
|
|
/// hanatoolbox import-rename SRC DST /path --replace
|
|
/// hanatoolbox cron setup
|
|
/// </summary>
|
|
public static CliArgs Parse(string[] args)
|
|
{
|
|
var positional = new List<string>();
|
|
var verbose = false;
|
|
var sid = string.Empty;
|
|
var compress = false;
|
|
var threads = 0;
|
|
var replace = false;
|
|
|
|
var command = string.Empty;
|
|
var subCommand = string.Empty;
|
|
|
|
int i = 0;
|
|
|
|
// First token that is not a flag is the command
|
|
// second non-flag token after that may be the subcommand (for "cron setup")
|
|
while (i < args.Length)
|
|
{
|
|
var a = args[i];
|
|
|
|
switch (a)
|
|
{
|
|
case "-v" or "--verbose":
|
|
verbose = true;
|
|
i++;
|
|
break;
|
|
|
|
case "--sid" when i + 1 < args.Length:
|
|
sid = args[++i];
|
|
i++;
|
|
break;
|
|
|
|
case "-c" or "--compress":
|
|
compress = true;
|
|
i++;
|
|
break;
|
|
|
|
case "--replace":
|
|
replace = true;
|
|
i++;
|
|
break;
|
|
|
|
case "-t" or "--threads" when i + 1 < args.Length:
|
|
int.TryParse(args[++i], out threads);
|
|
i++;
|
|
break;
|
|
|
|
default:
|
|
if (!a.StartsWith('-'))
|
|
{
|
|
if (string.IsNullOrEmpty(command))
|
|
command = a;
|
|
else if (string.IsNullOrEmpty(subCommand) && positional.Count == 0)
|
|
// Peek: is this a known subcommand for the current command?
|
|
subCommand = MaybeSubCommand(command, a) ? a : AddPositional(positional, a);
|
|
else
|
|
positional.Add(a);
|
|
}
|
|
// Unknown flag — silently skip
|
|
i++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return new CliArgs
|
|
{
|
|
Command = command,
|
|
SubCommand = subCommand,
|
|
Positional = positional,
|
|
Verbose = verbose,
|
|
Sid = sid,
|
|
Compress = compress,
|
|
Threads = threads,
|
|
Replace = replace,
|
|
};
|
|
}
|
|
|
|
// ── Helpers ───────────────────────────────────────────────────────────────
|
|
|
|
private static bool MaybeSubCommand(string command, string token) =>
|
|
command == "cron" && token == "setup";
|
|
|
|
private static string AddPositional(List<string> list, string value)
|
|
{
|
|
list.Add(value);
|
|
return string.Empty;
|
|
}
|
|
|
|
/// <summary>Gets positional arg at index, or empty string if not present.</summary>
|
|
public string Pos(int index) =>
|
|
index < Positional.Count ? Positional[index] : string.Empty;
|
|
}
|