示例#1
0
        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();
        }
示例#8
0
        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();
            }
        }
示例#11
0
        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}");
                        }
                    }
                }
            }
示例#12
0
        // 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, "  ");
示例#13
0
        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);
        }
示例#14
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);
        }
示例#15
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();
                    }
                }
            }
        }
示例#16
0
        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);
        }
示例#17
0
 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);
示例#20
0
 public static Task RunAsync(this TargetCollection targets, IEnumerable <string> args, IConsole console) =>
 RunAsync(targets ?? new TargetCollection(), args.Sanitize().ToList(), console ?? new SystemConsole());
示例#21
0
        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();
                    }
                }
            }
        }
示例#22
0
 public Task Targets(TargetCollection targets, List <string> rootTargets, int maxDepth, int maxDepthToShowInputs, bool listInputs) =>
 this.writer.WriteLineAsync(this.List(targets, rootTargets, maxDepth, maxDepthToShowInputs, listInputs));
示例#23
0
 public Task Usage(TargetCollection targets) => this.writer.WriteLineAsync(this.GetUsage(targets));