mirror of
https://github.com/actions/runner.git
synced 2025-12-11 04:46:58 +00:00
GitHub Actions Runner
This commit is contained in:
128
src/Runner.Common/CommandLineParser.cs
Normal file
128
src/Runner.Common/CommandLineParser.cs
Normal file
@@ -0,0 +1,128 @@
|
||||
using GitHub.Runner.Common.Util;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using GitHub.DistributedTask.Logging;
|
||||
using GitHub.Runner.Sdk;
|
||||
|
||||
//
|
||||
// Pattern:
|
||||
// cmd1 cmd2 --arg1 arg1val --aflag --arg2 arg2val
|
||||
//
|
||||
|
||||
namespace GitHub.Runner.Common
|
||||
{
|
||||
public sealed class CommandLineParser
|
||||
{
|
||||
private ISecretMasker _secretMasker;
|
||||
private Tracing _trace;
|
||||
|
||||
public List<string> Commands { get; }
|
||||
public HashSet<string> Flags { get; }
|
||||
public Dictionary<string, string> Args { get; }
|
||||
public HashSet<string> SecretArgNames { get; }
|
||||
private bool HasArgs { get; set; }
|
||||
|
||||
public CommandLineParser(IHostContext hostContext, string[] secretArgNames)
|
||||
{
|
||||
_secretMasker = hostContext.SecretMasker;
|
||||
_trace = hostContext.GetTrace(nameof(CommandLineParser));
|
||||
|
||||
Commands = new List<string>();
|
||||
Flags = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
Args = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
SecretArgNames = new HashSet<string>(secretArgNames ?? new string[0], StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public bool IsCommand(string name)
|
||||
{
|
||||
bool result = false;
|
||||
if (Commands.Count > 0)
|
||||
{
|
||||
result = String.Equals(name, Commands[0], StringComparison.CurrentCultureIgnoreCase);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Parse(string[] args)
|
||||
{
|
||||
_trace.Info(nameof(Parse));
|
||||
ArgUtil.NotNull(args, nameof(args));
|
||||
_trace.Info("Parsing {0} args", args.Length);
|
||||
|
||||
string argScope = null;
|
||||
foreach (string arg in args)
|
||||
{
|
||||
_trace.Info("parsing argument");
|
||||
|
||||
HasArgs = HasArgs || arg.StartsWith("--");
|
||||
_trace.Info("HasArgs: {0}", HasArgs);
|
||||
|
||||
if (string.Equals(arg, "/?", StringComparison.Ordinal))
|
||||
{
|
||||
Flags.Add("help");
|
||||
}
|
||||
else if (!HasArgs)
|
||||
{
|
||||
_trace.Info("Adding Command: {0}", arg);
|
||||
Commands.Add(arg.Trim());
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's either an arg, an arg value or a flag
|
||||
if (arg.StartsWith("--") && arg.Length > 2)
|
||||
{
|
||||
string argVal = arg.Substring(2);
|
||||
_trace.Info("arg: {0}", argVal);
|
||||
|
||||
// this means two --args in a row which means previous was a flag
|
||||
if (argScope != null)
|
||||
{
|
||||
_trace.Info("Adding flag: {0}", argScope);
|
||||
Flags.Add(argScope.Trim());
|
||||
}
|
||||
|
||||
argScope = argVal;
|
||||
}
|
||||
else if (!arg.StartsWith("-"))
|
||||
{
|
||||
// we found a value - check if we're in scope of an arg
|
||||
if (argScope != null && !Args.ContainsKey(argScope = argScope.Trim()))
|
||||
{
|
||||
if (SecretArgNames.Contains(argScope))
|
||||
{
|
||||
_secretMasker.AddValue(arg);
|
||||
}
|
||||
|
||||
_trace.Info("Adding option '{0}': '{1}'", argScope, arg);
|
||||
// ignore duplicates - first wins - below will be val1
|
||||
// --arg1 val1 --arg1 val1
|
||||
Args.Add(argScope, arg);
|
||||
argScope = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// ignoring the second value for an arg (val2 below)
|
||||
// --arg val1 val2
|
||||
|
||||
// ignoring invalid things like empty - and --
|
||||
// --arg val1 -- --flag
|
||||
_trace.Info("Ignoring arg");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_trace.Verbose("done parsing arguments");
|
||||
|
||||
// handle last arg being a flag
|
||||
if (argScope != null)
|
||||
{
|
||||
Flags.Add(argScope);
|
||||
}
|
||||
|
||||
_trace.Verbose("Exiting parse");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user