private static async Task RunAsync(this TargetCollection targets, List <string> args, IConsole console) { var(names, options) = args.Parse(); var log = await console.Initialize(options).ConfigureAwait(false); await RunAsync(targets, names, options, log, _ => false, args).ConfigureAwait(false); }
private static async Task RunAsync(TargetCollection targets, List <string> names, Options options, Func <Exception, bool> messageOnly, Output output, Logger log, bool exit) { if (exit) { try { await RunAsync(targets, names, options, messageOnly, output, log).Tax(); } catch (InvalidUsageException ex) { await log.Error(ex.Message).Tax(); Environment.Exit(2); } catch (TargetFailedException) { Environment.Exit(1); } Environment.Exit(0); } else { await RunAsync(targets, names, options, messageOnly, output, log).Tax(); } }
private static async Task RunAsync(this TargetCollection targets, List <string> args, Func <Exception, bool> messageOnly, string logPrefix) { var(names, options) = args.Parse(); var(output, log) = await ConsoleExtensions.Initialize(options, logPrefix).Tax(); await RunAsync(targets, names, options, output, log, messageOnly, args).Tax(); }
private static async Task RunAsync(this TargetCollection targets, List <string> names, Options options, Output output, Logger log, Func <Exception, bool> messageOnly, List <string> args) { if (options.UnknownOptions.Count > 0) { throw new InvalidUsageException($"Unknown option{(options.UnknownOptions.Count > 1 ? "s" : "")} {options.UnknownOptions.Spaced()}. \"--help\" for usage."); } await log.Verbose($"Args: {string.Join(" ", args)}").Tax(); if (options.ShowHelp) { await output.Usage(targets).Tax(); return; } if (options.ListTree || options.ListDependencies || options.ListInputs || options.ListTargets) { var rootTargets = names.Any() ? names : targets.Select(target => target.Name).OrderBy(name => name).ToList(); var maxDepth = options.ListTree ? int.MaxValue : options.ListDependencies ? 1 : 0; var maxDepthToShowInputs = options.ListTree ? int.MaxValue : 0; await output.Targets(targets, rootTargets, maxDepth, maxDepthToShowInputs, options.ListInputs).Tax(); return; } if (names.Count == 0) { names.Add("default"); } await targets.RunAsync(names, options.SkipDependencies, options.DryRun, options.Parallel, log, messageOnly).Tax(); }
public static Task RunAsync(this TargetCollection targets, IEnumerable <string> args, Func <Exception, bool> messageOnly, string logPrefix, bool exit) { var argList = args.Sanitize().ToList(); var(options, names) = Options.Parse(argList); return(RunAsync(targets, names, options, messageOnly, logPrefix, exit, log => log.Verbose(() => $"Args: {string.Join(" ", argList)}"))); }
private static async Task RunAsync(TargetCollection targets, List <string> names, Options options, Func <Exception, bool> messageOnly, string logPrefix, bool exit, Func <Logger, Task> logArgs) { targets = targets ?? new TargetCollection(); options = options ?? new Options(); messageOnly = messageOnly ?? (_ => false); if (logPrefix == null) { logPrefix = "Bullseye"; var entryAssembly = Assembly.GetEntryAssembly(); if (entryAssembly == null) { await Console.Error.WriteLineAsync($"{logPrefix}: Failed to get the entry assembly. Using default log prefix \"{logPrefix}\".").Tax(); } else { logPrefix = entryAssembly.GetName().Name; } } if (options.Clear) { try { Console.Clear(); } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { await Console.Error.WriteLineAsync($"{logPrefix}: Failed to clear the console: {ex}").Tax(); } } var operatingSystem = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? OperatingSystem.Windows : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? OperatingSystem.Linux : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? OperatingSystem.MacOS : OperatingSystem.Unknown; var terminal = await Terminal.TryConfigure(options.NoColor, operatingSystem, options.Verbose?Console.Error : NullTextWriter.Instance, logPrefix).Tax(); try { await RunAsync(targets, names, options, messageOnly, logPrefix, exit, logArgs, operatingSystem).Tax(); } finally { await terminal.DisposeAsync().Tax(); } }
public static async Task RunAsync(this TargetCollection targets, IEnumerable <string> names, Options options, Func <Exception, bool> messageOnly, string logPrefix, bool exit) { targets = targets ?? new TargetCollection(); var nameList = names.Sanitize().ToList(); options = options ?? new Options(); messageOnly = messageOnly ?? (_ => false); var(output, log) = await ConsoleExtensions.Initialize(options, logPrefix).Tax(); await RunAsync(targets, nameList, options, messageOnly, output, log, exit).Tax(); }
private string GetUsage(TargetCollection targets) => $@"{p.Default}Usage:{p.Reset} {p.CommandLine}<command-line>{p.Reset} {p.Option}[<options>]{p.Reset} {p.Target}[<targets>]{p.Reset} {p.Default}command-line: The command line which invokes the build targets.{p.Reset} {p.Default}Examples:{p.Reset} {p.CommandLine}build.cmd{p.Reset} {p.CommandLine}build.sh{p.Reset} {p.CommandLine}dotnet run --project targets --{p.Reset} {p.Default}options:{p.Reset} {p.Option}-c{p.Default},{p.Reset} {p.Option}--clear{p.Reset} {p.Default}Clear the console before execution{p.Reset} {p.Option}-n{p.Default},{p.Reset} {p.Option}--dry-run{p.Reset} {p.Default}Do a dry run without executing actions{p.Reset} {p.Option}-d{p.Default},{p.Reset} {p.Option}--list-dependencies{p.Reset} {p.Default}List all (or specified) targets and dependencies, then exit{p.Reset} {p.Option}-i{p.Default},{p.Reset} {p.Option}--list-inputs{p.Reset} {p.Default}List all (or specified) targets and inputs, then exit{p.Reset} {p.Option}-l{p.Default},{p.Reset} {p.Option}--list-targets{p.Reset} {p.Default}List all (or specified) targets, then exit{p.Reset} {p.Option}-t{p.Default},{p.Reset} {p.Option}--list-tree{p.Reset} {p.Default}List all (or specified) targets and dependency trees, then exit{p.Reset} {p.Option}-N{p.Default},{p.Reset} {p.Option}--no-color{p.Reset} {p.Default}Disable colored output{p.Reset} {p.Option}-E{p.Default},{p.Reset} {p.Option}--no-extended-chars{p.Reset} {p.Default}Disable extended characters{p.Reset} {p.Option}-p{p.Default},{p.Reset} {p.Option}--parallel{p.Reset} {p.Default}Run targets in parallel{p.Reset} {p.Option}-s{p.Default},{p.Reset} {p.Option}--skip-dependencies{p.Reset} {p.Default}Do not run targets' dependencies{p.Reset} {p.Option}-v{p.Default},{p.Reset} {p.Option}--verbose{p.Reset} {p.Default}Enable verbose output{p.Reset} {p.Option}--appveyor{p.Reset} {p.Default}Force Appveyor mode (normally auto-detected){p.Reset} {p.Option}--azure-pipelines{p.Reset} {p.Default}Force Azure Pipelines mode (normally auto-detected){p.Reset} {p.Option}--github-actions{p.Reset} {p.Default}Force GitHub Actions mode (normally auto-detected){p.Reset} {p.Option}--gitlab-ci{p.Reset} {p.Default}Force GitLab CI mode (normally auto-detected){p.Reset} {p.Option}--teamcity{p.Reset} {p.Default}Force TeamCity mode (normally auto-detected){p.Reset} {p.Option}--travis{p.Reset} {p.Default}Force Travis CI mode (normally auto-detected){p.Reset} {p.Option}-h{p.Default},{p.Reset} {p.Option}--help{p.Default},{p.Reset} {p.Option}-?{p.Reset} {p.Default}Show this help, then exit (case insensitive){p.Reset} {p.Default}targets: A list of targets to run or list.{p.Reset} {p.Default}If not specified, the {p.Target}""default""{p.Default} target will be run, or all targets will be listed.{p.Reset} {p.Default}Remarks:{p.Reset} {p.Default}The {p.Option}--list-xxx{p.Default} options can be combined.{p.Reset} {p.Default}Examples:{p.Reset} {p.CommandLine}build.cmd{p.Reset} {p.CommandLine}build.cmd{p.Reset} {p.Option}-D{p.Reset} {p.CommandLine}build.sh{p.Reset} {p.Option}-t{p.Reset} {p.Option}-I{p.Reset} {p.Target}default{p.Reset} {p.CommandLine}build.sh{p.Reset} {p.Target}test{p.Reset} {p.Target}pack{p.Reset} {p.CommandLine}dotnet run --project targets --{p.Reset} {p.Option}-n{p.Reset} {p.Target}build{p.Reset} {p.Default}Targets:{p.Reset} " + string.Join( @" ", targets.Select(target => $" {p.Target}{target.Name}{p.Reset}")) + @" ";
public static async Task RunAsync(this TargetCollection targets, IEnumerable <string> args, Func <Exception, bool> messageOnly, string logPrefix, bool exit) { targets = targets ?? new TargetCollection(); var argList = args.Sanitize().ToList(); messageOnly = messageOnly ?? (_ => false); var(options, names) = Options.Parse(argList); var(output, log) = await ConsoleExtensions.Initialize(options, logPrefix).Tax(); await log.Verbose($"Args: {string.Join(" ", argList)}").Tax(); await RunAsync(targets, names, options, messageOnly, output, log, exit).Tax(); }
private static async Task RunAsync(TargetCollection targets, List <string> names, Options options, Func <Exception, bool> messageOnly, string logPrefix, bool exit, Func <Logger, Task> logArgs, OperatingSystem operatingSystem) { var(host, isHostDetected) = options.Host.DetectIfUnknown(); var palette = new Palette(options.NoColor, options.NoExtendedChars, host, operatingSystem); var output = new Output(Console.Out, palette); var log = new Logger(Console.Error, logPrefix, options.SkipDependencies, options.DryRun, options.Parallel, palette, options.Verbose); await log.Version(() => typeof(TargetCollectionExtensions).Assembly.GetVersion()).Tax(); await log.Verbose(() => $"Host: {host}{(host != Host.Unknown ? $" ({(isHostDetected ? "detected" : "forced")})" : "")}").Tax(); await log.Verbose(() => $"OS: {operatingSystem}").Tax(); if (logArgs != null) { await logArgs(log).Tax(); } if (exit) { try { await RunAsync(targets, names, options, messageOnly, output, log).Tax(); } catch (InvalidUsageException ex) { await log.Error(ex.Message).Tax(); Environment.Exit(2); } catch (TargetFailedException) { Environment.Exit(1); } Environment.Exit(0); } else { await RunAsync(targets, names, options, messageOnly, output, log).Tax(); } }
private static string ToString(this TargetCollection targets, bool listDependencies, bool listInputs, Palette p) { var value = new StringBuilder(); foreach (var target in targets.OrderBy(target => target.Name)) { value.AppendLine($"{p.Target}{target.Name}{p.Default}"); if (listDependencies) { var writeHeader = listInputs; var indent = writeHeader ? " " : " "; foreach (var dependency in target.Dependencies) { if (writeHeader) { value.AppendLine($" {p.Label}Dependencies:{p.Default}"); writeHeader = false; } value.AppendLine($"{indent}{p.Dependency}{dependency}{(targets.Contains(dependency) ? "" : $" {p.Failed}(missing)")}{p.Default}"); } } if (listInputs) { var writeHeader = listDependencies; var indent = writeHeader ? " " : " "; if (target is IHaveInputs hasInputs) { foreach (var input in hasInputs.Inputs) { if (writeHeader) { value.AppendLine($" {p.Label}Inputs:{p.Default}"); writeHeader = false; } value.AppendLine($"{indent}{p.Input}{input}{p.Default}"); } } } }
// editorconfig-checker-disable private string GetUsage(TargetCollection targets) => $@"{p.Default}Usage:{p.Reset} {p.Invocation}[invocation]{p.Reset} {p.Option}[options]{p.Reset} {p.Target}[<targets>...]{p.Reset} {p.Default}Arguments:{p.Reset} {p.Target}<targets>{p.Reset} {p.Default}A list of targets to run or list. If not specified, the {p.Target}""default""{p.Default} target will be run, or all targets will be listed.{p.Reset} {p.Default}Options:{p.Reset} {p.Option}-c{p.Default},{p.Reset} {p.Option}--clear{p.Reset} {p.Default}Clear the console before execution{p.Reset} {p.Option}-n{p.Default},{p.Reset} {p.Option}--dry-run{p.Reset} {p.Default}Do a dry run without executing actions{p.Reset} {p.Option}-d{p.Default},{p.Reset} {p.Option}--list-dependencies{p.Reset} {p.Default}List all (or specified) targets and dependencies, then exit{p.Reset} {p.Option}-i{p.Default},{p.Reset} {p.Option}--list-inputs{p.Reset} {p.Default}List all (or specified) targets and inputs, then exit{p.Reset} {p.Option}-l{p.Default},{p.Reset} {p.Option}--list-targets{p.Reset} {p.Default}List all (or specified) targets, then exit{p.Reset} {p.Option}-t{p.Default},{p.Reset} {p.Option}--list-tree{p.Reset} {p.Default}List all (or specified) targets and dependency trees, then exit{p.Reset} {p.Option}-N{p.Default},{p.Reset} {p.Option}--no-color{p.Reset} {p.Default}Disable colored output{p.Reset} {p.Option}-E{p.Default},{p.Reset} {p.Option}--no-extended-chars{p.Reset} {p.Default}Disable extended characters{p.Reset} {p.Option}-p{p.Default},{p.Reset} {p.Option}--parallel{p.Reset} {p.Default}Run targets in parallel{p.Reset} {p.Option}-s{p.Default},{p.Reset} {p.Option}--skip-dependencies{p.Reset} {p.Default}Do not run targets' dependencies{p.Reset} {p.Option}-v{p.Default},{p.Reset} {p.Option}--verbose{p.Reset} {p.Default}Enable verbose output{p.Reset} {p.Option}--appveyor{p.Reset} {p.Default}Force Appveyor mode (normally auto-detected){p.Reset} {p.Option}--azure-pipelines{p.Reset} {p.Default}Force Azure Pipelines mode (normally auto-detected){p.Reset} {p.Option}--github-actions{p.Reset} {p.Default}Force GitHub Actions mode (normally auto-detected){p.Reset} {p.Option}--gitlab-ci{p.Reset} {p.Default}Force GitLab CI mode (normally auto-detected){p.Reset} {p.Option}--teamcity{p.Reset} {p.Default}Force TeamCity mode (normally auto-detected){p.Reset} {p.Option}--travis{p.Reset} {p.Default}Force Travis CI mode (normally auto-detected){p.Reset} {p.Option}-?{p.Default},{p.Reset} {p.Option}-h{p.Default},{p.Reset} {p.Option}--help{p.Reset} {p.Default}Show help and usage information, then exit (case insensitive){p.Reset} {p.Default}Remarks:{p.Reset} {p.Default}The {p.Option}--list-xxx{p.Default} options may be combined.{p.Reset} {p.Default}The {p.Invocation}invocation{p.Reset} is typically a call to dotnet run, or the path to a script which wraps a call to dotnet run. {p.Default}Examples:{p.Reset} {p.Invocation}./build.{scriptExtension}{p.Reset} {p.Invocation}./build.{scriptExtension}{p.Reset} {p.Option}-d{p.Reset} {p.Invocation}./build.{scriptExtension}{p.Reset} {p.Option}-t{p.Reset} {p.Option}-i{p.Reset} {p.Target}default{p.Reset} {p.Invocation}./build.{scriptExtension}{p.Reset} {p.Target}test{p.Reset} {p.Target}pack{p.Reset} {p.Invocation}dotnet run --project targets --{p.Reset} {p.Option}-n{p.Reset} {p.Target}build{p.Reset} {p.Default}Targets:{p.Reset} " + List(targets, targets.Select(target => target.Name).ToList(), 0, 0, false, " ");
private static async Task RunAndExitAsync(this TargetCollection targets, List <string> args, Func <Exception, bool> messageOnly, string logPrefix) { var(names, options) = args.Parse(); var(output, log) = await ConsoleExtensions.Initialize(options, logPrefix).Tax(); try { await RunAsync(targets, names, options, output, log, messageOnly, args).Tax(); } catch (InvalidUsageException ex) { await log.Error(ex.Message).Tax(); Environment.Exit(2); } catch (TargetFailedException) { Environment.Exit(1); } Environment.Exit(0); }
private static async Task RunAndExitAsync(this TargetCollection targets, List <string> args, IConsole console, Func <Exception, bool> messageOnly) { var(names, options) = args.Parse(); var log = await console.Initialize(options).ConfigureAwait(false); try { await RunAsync(targets, names, options, log, messageOnly, args).ConfigureAwait(false); } catch (InvalidUsageException ex) { await log.Error(ex.Message).ConfigureAwait(false); Environment.Exit(2); } catch (TargetFailedException) { Environment.Exit(1); } Environment.Exit(0); }
private string List(TargetCollection targets, List <string> rootTargets, int maxDepth, int maxDepthToShowInputs, bool listInputs) { var value = new StringBuilder(); foreach (var rootTarget in rootTargets) { Append(new List <string> { rootTarget }, new Stack <string>(), true, "", 0); } return(value.ToString()); void Append(List <string> names, Stack <string> seenTargets, bool isRoot, string previousPrefix, int depth) { if (depth > maxDepth) { return; } foreach (var item in names.Select((name, index) => new { name, index })) { var circularDependency = seenTargets.Contains(item.name); seenTargets.Push(item.name); try { var prefix = isRoot ? "" : $"{previousPrefix.Replace(p.TreeCorner, " ").Replace(p.TreeFork, p.TreeDown)}{(item.index == names.Count - 1 ? p.TreeCorner : p.TreeFork)}"; var isMissing = !targets.Contains(item.name); value.Append($"{p.Tree}{prefix}{(isRoot ? p.Target : p.Dependency)}{item.name}{p.Default}"); if (isMissing) { value.AppendLine($" {p.Failed}(missing){p.Default}"); continue; } if (circularDependency) { value.AppendLine($" {p.Failed}(circular dependency){p.Default}"); continue; } value.AppendLine(p.Default); var target = targets[item.name]; if (listInputs && depth <= maxDepthToShowInputs && target is IHaveInputs hasInputs) { foreach (var inputItem in hasInputs.Inputs.Select((input, index) => new { input, index })) { var inputPrefix = $"{prefix.Replace(p.TreeCorner, " ").Replace(p.TreeFork, p.TreeDown)}{(target.Dependencies.Any() && depth + 1 <= maxDepth ? p.TreeDown : " ")}"; value.AppendLine($"{p.Tree}{inputPrefix}{p.Input}{inputItem.input}{p.Default}"); } } Append(target.Dependencies, seenTargets, false, prefix, depth + 1); } finally { seenTargets.Pop(); } } } }
private static async Task RunAsync(this TargetCollection targets, List <string> args, IConsole console) { var clear = false; var dryRun = false; var listDependencies = false; var listInputs = false; var listTargets = false; var noColor = false; var parallel = false; var skipDependencies = false; var verbose = false; var host = Host.Unknown; var showHelp = false; var helpOptions = new[] { "--help", "-h", "-?" }; var optionsArgs = args.Where(arg => arg.StartsWith("-", StringComparison.Ordinal)).ToList(); var unknownOptions = new List <string>(); foreach (var option in optionsArgs) { switch (option) { case "-c": case "--clear": clear = true; break; case "-n": case "--dry-run": dryRun = true; break; case "-D": case "--list-dependencies": listDependencies = true; break; case "-I": case "--list-inputs": listInputs = true; break; case "-T": case "--list-targets": listTargets = true; break; case "-N": case "--no-color": noColor = true; break; case "-p": case "--parallel": parallel = true; break; case "-s": case "--skip-dependencies": skipDependencies = true; break; case "-v": case "--verbose": verbose = true; break; case "--appveyor": host = Host.Appveyor; break; case "--travis": host = Host.Travis; break; case "--teamcity": host = Host.TeamCity; break; default: if (helpOptions.Contains(option, StringComparer.OrdinalIgnoreCase)) { showHelp = true; } else { unknownOptions.Add(option); } break; } } if (unknownOptions.Count > 0) { throw new BullseyeException($"Unknown option{(unknownOptions.Count > 1 ? "s" : "")} {unknownOptions.Spaced()}. \"--help\" for usage."); } if (clear) { console.Clear(); } var operatingSystem = OperatingSystem.Unknown; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { operatingSystem = OperatingSystem.Windows; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { operatingSystem = OperatingSystem.Linux; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { operatingSystem = OperatingSystem.MacOS; } if (!noColor && operatingSystem == OperatingSystem.Windows) { await WindowsConsole.TryEnableVirtualTerminalProcessing(console.Out, verbose).ConfigureAwait(false); } var isHostForced = true; if (host == Host.Unknown) { isHostForced = false; if (Environment.GetEnvironmentVariable("APPVEYOR")?.ToUpperInvariant() == "TRUE") { host = Host.Appveyor; } else if (!string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TRAVIS_OS_NAME"))) { host = Host.Travis; } else if (!string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TEAMCITY_PROJECT_NAME"))) { host = Host.TeamCity; } } var palette = new Palette(noColor, host, operatingSystem); var log = new Logger(console, skipDependencies, dryRun, parallel, palette, verbose); await log.Version().ConfigureAwait(false); await log.Verbose($"Host: {host}{(host != Host.Unknown ? $" ({(isHostForced ? "forced" : "detected")})" : "")}").ConfigureAwait(false); await log.Verbose($"OS: {operatingSystem}").ConfigureAwait(false); await log.Verbose($"Args: {string.Join(" ", args)}").ConfigureAwait(false); if (showHelp) { await console.Out.WriteLineAsync(GetUsage(palette)).ConfigureAwait(false); return; } if (listDependencies || listInputs || listTargets) { await console.Out.WriteLineAsync(targets.ToString(listDependencies, listInputs, palette)).ConfigureAwait(false); return; } var names = args.Where(arg => !arg.StartsWith("-")).ToList(); if (names.Count == 0) { names.Add("default"); } await targets.RunAsync(names, skipDependencies, dryRun, parallel, log).ConfigureAwait(false); }
public static Task RunAndExitAsync(this TargetCollection targets, IEnumerable <string> args, Func <Exception, bool> messageOnly, string logPrefix) => RunAndExitAsync(targets ?? new TargetCollection(), args.Sanitize().ToList(), messageOnly ?? (_ => false), logPrefix);
private static async Task RunAsync(TargetCollection targets, List <string> names, Options options, Func <Exception, bool> messageOnly, string logPrefix, bool exit, Func <Logger, Task> logArgs) { targets = targets ?? new TargetCollection(); options = options ?? new Options(); messageOnly = messageOnly ?? (_ => false); if (logPrefix == null) { logPrefix = "Bullseye"; var entryAssembly = Assembly.GetEntryAssembly(); if (entryAssembly == null) { await Console.Error.WriteLineAsync($"{logPrefix}: Failed to get the entry assembly. Using default log prefix \"{logPrefix}\".").Tax(); } else { logPrefix = entryAssembly.GetName().Name; } } if (options.Clear) { try { Console.Clear(); } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { await Console.Error.WriteLineAsync($"{logPrefix}: Failed to clear the console: {ex}").Tax(); } } var operatingSystem = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? OperatingSystem.Windows : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? OperatingSystem.Linux : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? OperatingSystem.MacOS : OperatingSystem.Unknown; if (!options.NoColor && operatingSystem == OperatingSystem.Windows) { await WindowsConsole.TryEnableVirtualTerminalProcessing(options.Verbose?Console.Error : NullTextWriter.Instance, logPrefix).Tax(); } var(host, isHostDetected) = options.Host.DetectIfUnknown(); var palette = new Palette(options.NoColor, options.NoExtendedChars, host, operatingSystem); var output = new Output(Console.Out, palette); var log = new Logger(Console.Error, logPrefix, options.SkipDependencies, options.DryRun, options.Parallel, palette, options.Verbose); await log.Version(() => typeof(TargetCollectionExtensions).Assembly.GetVersion()).Tax(); await log.Verbose(() => $"Host: {host}{(host != Host.Unknown ? $" ({(isHostDetected ? "detected" : "forced")})" : "")}").Tax(); await log.Verbose(() => $"OS: {operatingSystem}").Tax(); if (logArgs != null) { await logArgs(log).Tax(); } if (exit) { try { await RunAsync(targets, names, options, messageOnly, output, log).Tax(); } catch (InvalidUsageException ex) { await log.Error(ex.Message).Tax(); Environment.Exit(2); } catch (TargetFailedException) { Environment.Exit(1); } Environment.Exit(0); } else { await RunAsync(targets, names, options, messageOnly, output, log).Tax(); } }
public static Task RunAsync(this TargetCollection targets, IEnumerable <string> names, Options options, Func <Exception, bool> messageOnly, string logPrefix, bool exit) => RunAsync(targets, names.Sanitize().ToList(), options, messageOnly, logPrefix, exit, default);
public static Task RunAsync(this TargetCollection targets, IEnumerable <string> args, IConsole console) => RunAsync(targets ?? new TargetCollection(), args.Sanitize().ToList(), console ?? new SystemConsole());
private string List(TargetCollection targets, List <string> rootTargets, int maxDepth, int maxDepthToShowInputs, bool listInputs, string startingPrefix) { var lines = new List <(string, string)>(); foreach (var rootTarget in rootTargets) { Append(new List <string> { rootTarget }, new Stack <string>(), true, "", 0); } var maxColumn1Width = lines.Max(line => Palette.StripColours(line.Item1).Length); return(string.Join("", lines.Select(line => $"{line.Item1.PadRight(maxColumn1Width + line.Item1.Length - Palette.StripColours(line.Item1).Length)} {line.Item2}{Environment.NewLine}"))); void Append(List <string> names, Stack <string> seenTargets, bool isRoot, string previousPrefix, int depth) { if (depth > maxDepth) { return; } foreach (var item in names.Select((name, index) => new { name, index })) { var circularDependency = seenTargets.Contains(item.name); seenTargets.Push(item.name); try { var prefix = isRoot ? startingPrefix ?? "" : $"{previousPrefix.Replace(p.TreeCorner, " ").Replace(p.TreeFork, p.TreeDown)}{(item.index == names.Count - 1 ? p.TreeCorner : p.TreeFork)}"; var isMissing = !targets.Contains(item.name); var line = $"{prefix}{p.Target}{item.name}"; if (isMissing) { lines.Add((line + $"{p.Reset} {p.Failed}(missing){p.Reset}", null)); continue; } if (circularDependency) { lines.Add((line + $"{p.Reset} {p.Failed}(circular dependency){p.Reset}", targets[item.name].Description)); continue; } lines.Add((line + p.Reset, targets[item.name].Description)); var target = targets[item.name]; if (listInputs && depth <= maxDepthToShowInputs && target is IHaveInputs hasInputs) { foreach (var inputItem in hasInputs.Inputs.Select((input, index) => new { input, index })) { var inputPrefix = $"{prefix.Replace(p.TreeCorner, " ").Replace(p.TreeFork, p.TreeDown)}{(target.Dependencies.Any() && depth + 1 <= maxDepth ? p.TreeDown : " ")}"; lines.Add(($"{inputPrefix}{p.Input}{inputItem.input}{p.Reset}", null)); } } Append(target.Dependencies, seenTargets, false, prefix, depth + 1); } finally { seenTargets.Pop(); } } } }
public Task Targets(TargetCollection targets, List <string> rootTargets, int maxDepth, int maxDepthToShowInputs, bool listInputs) => this.writer.WriteLineAsync(this.List(targets, rootTargets, maxDepth, maxDepthToShowInputs, listInputs));
public Task Usage(TargetCollection targets) => this.writer.WriteLineAsync(this.GetUsage(targets));