Exemple #1
0
    public static string Command(string executable, string arguments, string workingDirectory)
    {
        var stdOutBuffer = new StringBuilder();
        var stdErrBuffer = new StringBuilder();

        var command = CliWrap.Cli.Wrap(executable).WithArguments(
            args => args
            .Add(arguments.Split())
            )
                      .WithWorkingDirectory(workingDirectory)
                      .WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdOutBuffer))
                      .WithStandardErrorPipe(PipeTarget.ToStringBuilder(stdErrBuffer));

        try
        {
            using var task = command.ExecuteAsync().Task;
            task.Wait();
        }
        catch (AggregateException)
        {
            throw new IOException(stdErrBuffer.ToString());
        }

        return(stdOutBuffer.ToString());
    }
        internal static async Task <string> ExecuteInternal(Action <ArgumentsBuilder> configure, CancellationToken cancellationToken)
        {
            var toolPath = ToolPath;

            ThrowIfNull(toolPath, nameof(Emulator));
            var builder = new ArgumentsBuilder();

            configure(builder);
            var args = builder.Build();

            Logger.WriteLine($"{toolPath} {args}", LogLevel.Normal);
            var stdErrBuffer = new StringBuilder();
            var stdOutBuffer = new StringBuilder();
            var stdOut       = PipeTarget.Merge(PipeTarget.ToStringBuilder(stdOutBuffer),
                                                PipeTarget.ToDelegate(l => Logger.WriteLine(l, LogLevel.Verbose)));

            await Cli.Wrap(toolPath)
            .WithArguments(args)
            .WithStandardErrorPipe(PipeTarget.ToStringBuilder(stdErrBuffer))
            .WithStandardOutputPipe(stdOut)
            .ExecuteAsync(cancellationToken);

            var stdErr = stdErrBuffer.ToString().Trim();

            if (!string.IsNullOrEmpty(stdErr))
            {
                throw new Exception(stdErr);
            }

            return(stdOutBuffer.ToString().Trim());
        }
Exemple #3
0
        public async Task <string> DownloadMediaFile(string id, string outputDirectory, string _, CancellationToken ct)
        {
            var tcs = new TaskCompletionSource <object>();

            var stdout  = new StringBuilder();
            var stderr  = new StringBuilder();
            var command = $"youtube-dl -o \"%(title)s-%(id)s.%(ext)s\" -f worst --write-info-json \"{id}\"";
            var cmd     = Cli.Wrap("youtube-dl")
                          .WithArguments($"-o \"%(title)s-%(id)s.%(ext)s\" -f worst --write-info-json \"{id}\"")
                          .WithWorkingDirectory(outputDirectory)
                          .WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdout))
                          .WithStandardErrorPipe(PipeTarget.ToStringBuilder(stderr));

            try
            {
                await cmd.ExecuteAsync(ct);
            } catch (Exception)
            {
                throw new Exception(stderr.ToString());
            }

            var fileInfo = GetFileInfo(stdout.ToString(), outputDirectory);

            return(fileInfo.FileName);
        }
Exemple #4
0
        public static async Task <bool> InstallPackage(string packageName, CancellationToken cancellationToken)
        {
            Console.WriteLine($"npm install -g {packageName}");
            var stdErrBuffer = new StringBuilder();
            var stdOut       = PipeTarget.ToDelegate(l => Console.WriteLine(l));
            await Cli.Wrap("npm")
            .WithArguments($"install -g {packageName}")
            .WithStandardOutputPipe(stdOut)
            .WithStandardErrorPipe(PipeTarget.ToStringBuilder(stdErrBuffer))
            .ExecuteAsync(cancellationToken);

            if (cancellationToken.IsCancellationRequested)
            {
                return(false);
            }

            var errorOutput = stdErrBuffer.ToString().Trim();

            if (string.IsNullOrEmpty(errorOutput))
            {
                return(true);
            }

            throw new Exception(errorOutput);
        }
Exemple #5
0
        internal static async Task ExecuteInternal(Action <ArgumentsBuilder> configure, CancellationToken cancellationToken)
        {
            ThrowIfNull(ToolPath, nameof(SdkManager));

            var stdErrBuffer = new StringBuilder();
            await Cli.Wrap(ToolPath)
            .WithArguments(configure)
            .WithValidation(CommandResultValidation.None)
            .WithStandardErrorPipe(PipeTarget.ToStringBuilder(stdErrBuffer))
            .WithStandardOutputPipe(PipeTarget.ToDelegate(l => Logger.WriteLine(l, LogLevel.Detailed)))
            .WithStandardInputPipe(PipeSource.FromString("y"))
            .ExecuteAsync(cancellationToken);

            var stdErr = stdErrBuffer.ToString().Trim();

            if (!string.IsNullOrEmpty(stdErr))
            {
                if (stdErr.Split('\n').Select(x => x.Trim()).All(x => x.StartsWith("Warning:")))
                {
                    Logger.WriteWarning(stdErr);
                }
                else
                {
                    throw new Exception(stdErr);
                }
            }
        }
Exemple #6
0
        private static async Task Execute(string args, LogLevel logLevel, CancellationToken cancellationToken)
        {
            Logger.WriteLine($"{DotNetExe.FullPath} {args}", LogLevel.Normal);
            var stdErrBuffer = new StringBuilder();
            var stdOut       = PipeTarget.ToDelegate(l => Logger.WriteLine(l, logLevel));
            var stdErr       = PipeTarget.ToStringBuilder(stdErrBuffer);

            var result = await Cli.Wrap(DotNetExe.FullPath)
                         .WithArguments(args)
                         .WithStandardErrorPipe(stdOut)
                         .WithStandardErrorPipe(stdErr)
                         .WithValidation(CommandResultValidation.None)
                         .ExecuteAsync(cancellationToken)
                         .ConfigureAwait(false);

            var error = stdErrBuffer.ToString().Trim();

            if (!string.IsNullOrEmpty(error))
            {
                throw new Exception(error);
            }

            if (result.ExitCode > 0)
            {
                throw new Exception($"The dotnet tool unexpectidly exited without any error output with code: {result.ExitCode}");
            }
        }
Exemple #7
0
        public static EsiSystem ConvertTextSchema(EsiContext ctxt, FileInfo file)
        {
            var exeDir = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName;

            using (var memstream = new MemoryStream())
            {
                var errorStringBuilder = new StringBuilder();
                var capnpCmd           = Cli.Wrap("capnp")
                                         .WithEnvironmentVariables(new Dictionary <string, string>()
                {
                    ["LD_LIBRARY_PATH"] = exeDir
                })
                                         .WithArguments($"compile -I{Path.Join(Esi.Utils.RootDir.FullName, "capnp.convert")} -o- {file.FullName}")
                                         .WithStandardOutputPipe(PipeTarget.ToStream(memstream))
                                         .WithStandardErrorPipe(PipeTarget.ToStringBuilder(errorStringBuilder))
                                         .WithValidation(CommandResultValidation.ZeroExitCode);

                try
                {
                    Task.Run(async() => await capnpCmd.ExecuteAsync()).Wait();
                }
                catch (AggregateException ex)
                {
                    if (ex.InnerException is CommandExecutionException cee)
                    {
                        ctxt.Log.Error($"CapNProto Error:\n{errorStringBuilder.ToString()}");
                    }
                    ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
                }
                Debug.Assert(memstream.Length > 0);

                memstream.Seek(0, SeekOrigin.Begin);
                return(ConvertFromCGRMessage(ctxt, memstream));
            }
        }
Exemple #8
0
        public async Task Serialize(TestDescription testDescription)
        {
            var extension      = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : "";
            var execPath       = Path.Combine(testDescription.Directory, testDescription.Name + extension);
            var standardOutput = new StringBuilder();
            var errorOutput    = new StringBuilder();

            try
            {
                await Cli.Wrap(execPath)
                .WithArguments("Serialize")
                .WithStandardOutputPipe(PipeTarget.ToStringBuilder(standardOutput))
                .WithStandardErrorPipe(PipeTarget.ToStringBuilder(errorOutput))
                .ExecuteAsync();
            }
            catch (Exception e)
            {
                throw new Exception("Failed to run serialization for version " + testDescription.Name, e);
            }
            finally
            {
                Console.WriteLine(errorOutput.ToString());
                Console.WriteLine(standardOutput.ToString());
            }
        }
Exemple #9
0
        internal static async Task ExecuteInternal(Action <ArgumentsBuilder> configure, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return;
            }

            var builder = new ArgumentsBuilder();

            configure(builder);
            var args = builder.Build();

            Logger.WriteLine($"{ToolPath} {args}", LogLevel.Normal);
            var stdOutBuffer = new StringBuilder();
            var stdOut       = PipeTarget.Merge(PipeTarget.ToStringBuilder(stdOutBuffer),
                                                PipeTarget.ToDelegate(l => Logger.WriteLine(l, LogLevel.Verbose)));
            var stdError = PipeTarget.ToDelegate(l =>
            {
                if (string.IsNullOrEmpty(l))
                {
                    return;
                }

                // Suppress errors
                Logger.WriteWarning(l);
            });

            var result = await Cli.Wrap(ToolPath)
                         .WithArguments(args)
                         .WithValidation(CommandResultValidation.None)
                         .WithStandardErrorPipe(stdError)
                         .WithStandardOutputPipe(stdOut)
                         .ExecuteAsync(cancellationToken);
        }
        private static async Task <bool> IsValidVideoFile(FileSystemInfo file, FrameFinderOptions frameFinderOptions)
        {
            var standardOutput      = new StringBuilder();
            var standardErrorOutput = new StringBuilder();

            var result = await Cli.Wrap(frameFinderOptions.FFprobeBinaryPath)
                         .WithArguments($"-print_format json -show_format -show_streams \"{file.FullName}\"")
                         .WithStandardOutputPipe(PipeTarget.ToStringBuilder(standardOutput))
                         .WithStandardErrorPipe(PipeTarget.ToStringBuilder(standardErrorOutput))
                         .WithValidation(CommandResultValidation.None)
                         .ExecuteAsync();

            if (result.ExitCode == 0)
            {
                var json   = standardOutput.ToString();
                var parsed = JsonSerializer.Deserialize <FFprobeOutput>(json);

                if (parsed?.Format.Duration == null)
                {
                    return(false);
                }

                var parsedDuration = double.Parse(parsed.Format.Duration, CultureInfo.InvariantCulture);
                var duration       = TimeSpan.FromSeconds(parsedDuration);
                return(duration > frameFinderOptions.MinimumIntroTime);
            }

            return(false);
        }
Exemple #11
0
        private static async Task <string> ExecuteInternal(Action <ArgumentsBuilder> configure, CancellationToken cancellationToken, PipeSource stdInput = null)
        {
            var toolPath = ToolPath;

            ThrowIfNull(toolPath, nameof(AvdManager));
            var builder = new ArgumentsBuilder();

            configure(builder);
            var args = builder.Build();

            Logger.WriteLine($"{toolPath} {args}", LogLevel.Normal);
            var errorBuffer  = new List <string>();
            var stdOutBuffer = new StringBuilder();
            var stdOut       = PipeTarget.Merge(PipeTarget.ToStringBuilder(stdOutBuffer),
                                                PipeTarget.ToDelegate(l => Logger.WriteLine(l, LogLevel.Verbose)));

            var stdErr = PipeTarget.ToDelegate(l =>
            {
                if (string.IsNullOrEmpty(l))
                {
                    return;
                }
                else if (l.Contains("Warning: "))
                {
                    Logger.WriteWarning(l);
                }
                else
                {
                    errorBuffer.Add(l);
                }
            });

            var cmd = Cli.Wrap(toolPath)
                      .WithArguments(args)
                      .WithValidation(CommandResultValidation.None)
                      .WithStandardErrorPipe(stdErr)
                      .WithStandardOutputPipe(stdOut);

            if (stdInput != null)
            {
                cmd = cmd.WithStandardInputPipe(stdInput);
            }

            await cmd.ExecuteAsync(cancellationToken);

            if (errorBuffer.Any())
            {
                throw new Exception(string.Join(Environment.NewLine, errorBuffer));
            }

            return(stdOutBuffer.ToString().Trim());
        }
Exemple #12
0
        public static async Task Build(string projectPath, string baseWorkingDirectory, IDictionary <string, string> props, CancellationToken cancellationToken, string target = null)
        {
            if (string.IsNullOrEmpty(ToolPath))
            {
                throw new Exception("No installation of Visual Studio could be found. Could not locate msbuild.");
            }

            if (!props.ContainsKey("Configuration"))
            {
                props.Add("Configuration", "Release");
            }

            if (!props.ContainsKey("Verbosity"))
            {
                props.Add("Verbosity", "Minimal");
            }

            var stdErrBuffer = new StringBuilder();
            var result       = await Cli.Wrap(ToolPath)
                               .WithArguments(b =>
            {
                b.Add(projectPath);

                b.Add("/r");

                if (!string.IsNullOrEmpty(target))
                {
                    b.Add($"/t:{target}");
                }

                foreach ((var key, var value) in props)
                {
                    b.Add($"/p:{key}={value}");
                }

                var logoutput = Path.Combine(baseWorkingDirectory, "logs", $"{Path.GetFileNameWithoutExtension(projectPath)}.binlog");
                b.Add($"/bl:{logoutput}");
            })
                               .WithStandardOutputPipe(PipeTarget.ToDelegate(l => Logger.WriteLine(l, LogLevel.Normal)))
                               .WithStandardErrorPipe(PipeTarget.ToStringBuilder(stdErrBuffer))
                               .WithValidation(CommandResultValidation.None)
                               .ExecuteAsync(cancellationToken)
                               .ConfigureAwait(false);

            var error = stdErrBuffer.ToString().Trim();

            if (!string.IsNullOrEmpty(error))
            {
                throw new Exception(error);
            }
        }
        /// <summary>
        /// Executes the command asynchronously.
        /// The result of this execution contains the standard output and standard error streams buffered in-memory as strings.
        /// This method can be awaited.
        /// </summary>
        public static CommandTask <BufferedCommandResult> ExecuteBufferedAsync(
            this Command command,
            Encoding standardOutputEncoding,
            Encoding standardErrorEncoding,
            CancellationToken cancellationToken = default)
        {
            var stdOutBuffer = new StringBuilder();
            var stdErrBuffer = new StringBuilder();

            var stdOutPipe = PipeTarget.Merge(
                command.StandardOutputPipe,
                PipeTarget.ToStringBuilder(stdOutBuffer, standardOutputEncoding)
                );

            var stdErrPipe = PipeTarget.Merge(
                command.StandardErrorPipe,
                PipeTarget.ToStringBuilder(stdErrBuffer, standardErrorEncoding)
                );

            var commandPiped = command
                               .WithStandardOutputPipe(stdOutPipe)
                               .WithStandardErrorPipe(stdErrPipe)
                               .WithValidation(CommandResultValidation.None); // disable validation because we have our own

            return(commandPiped
                   .ExecuteAsync(cancellationToken)
                   .Select(r =>
            {
                // Transform the result
                var result = new BufferedCommandResult(
                    r.ExitCode,
                    r.StartTime,
                    r.ExitTime,
                    stdOutBuffer.ToString(),
                    stdErrBuffer.ToString()
                    );

                // We perform validation separately here because we want to include stderr in the exception as well
                if (result.ExitCode != 0 && command.Validation.IsZeroExitCodeValidationEnabled())
                {
                    throw CommandExecutionException.ExitCodeValidation(
                        command.TargetFilePath,
                        command.Arguments,
                        result.ExitCode,
                        result.StandardError.Trim()
                        );
                }

                return result;
            }));
        }
Exemple #14
0
        private async Task <CommandResult> RunAsyncInner(
            IEnumerable <string> args,
            string workingDir,
            IDictionary <string, string?> additionalEnv,
            Action <string>?onStandardOutput    = null,
            Action <string>?onStandardError     = null,
            EventLogFile?eventLogFile           = null,
            CancellationToken cancellationToken = default)
        {
            var stdOutBuffer = new StringBuilder();
            var stdOutPipe   = PipeTarget.ToStringBuilder(stdOutBuffer);

            if (onStandardOutput != null)
            {
                stdOutPipe = PipeTarget.Merge(stdOutPipe, PipeTarget.ToDelegate(onStandardOutput));
            }

            var stdErrBuffer = new StringBuilder();
            var stdErrPipe   = PipeTarget.ToStringBuilder(stdErrBuffer);

            if (onStandardError != null)
            {
                stdErrPipe = PipeTarget.Merge(stdErrPipe, PipeTarget.ToDelegate(onStandardError));
            }

            var pulumiCmd = Cli.Wrap("pulumi")
                            .WithArguments(PulumiArgs(args, eventLogFile), escape: true)
                            .WithWorkingDirectory(workingDir)
                            .WithEnvironmentVariables(PulumiEnvironment(additionalEnv, debugCommands: eventLogFile != null))
                            .WithStandardOutputPipe(stdOutPipe)
                            .WithStandardErrorPipe(stdErrPipe)
                            .WithValidation(CommandResultValidation.None); // we check non-0 exit code ourselves

            var pulumiCmdResult = await pulumiCmd.ExecuteAsync(cancellationToken);

            var result = new CommandResult(
                pulumiCmdResult.ExitCode,
                standardOutput: stdOutBuffer.ToString(),
                standardError: stdErrBuffer.ToString());

            if (pulumiCmdResult.ExitCode != 0)
            {
                throw CommandException.CreateFromResult(result);
            }
            else
            {
                return(result);
            }
        }
Exemple #15
0
        public static async Task <ConversionResult> Docx2HubAsync(string inputDocxPath)
        {
            if (!File.Exists(inputDocxPath))
            {
                throw new FileNotFoundException($"{nameof(inputDocxPath)} does not exists");
            }
            ConversionResult res = null;
            var targetDir        = Path.GetDirectoryName(inputDocxPath);

            var stdOutBuffer = new StringBuilder();
            var stdErrBuffer = new StringBuilder();

            var script = "/opt/docx2hub/docx2hub.sh";
            var cmd    = CliWrap.Cli.Wrap("/bin/bash")
                         .WithArguments($"-c \"{script} -o {targetDir} '{inputDocxPath}'\"")
                         .WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdOutBuffer))
                         .WithStandardErrorPipe(PipeTarget.ToStringBuilder(stdErrBuffer))
                         .WithValidation(CommandResultValidation.None);
            var expectedLogPath        = Path.Combine(Path.GetDirectoryName(inputDocxPath), Path.GetFileNameWithoutExtension(inputDocxPath) + ".log");
            var expectedResultFilePath = Path.Combine(Path.GetDirectoryName(inputDocxPath), Path.GetFileNameWithoutExtension(inputDocxPath) + ".xml");

            try {
                var cmdRes = await cmd.ExecuteAsync();

                res = new ConversionResult()
                {
                    StdErr         = stdErrBuffer.ToString(),
                    StdOut         = stdOutBuffer.ToString(),
                    ExitCode       = cmdRes.ExitCode,
                    StartTime      = cmdRes.StartTime,
                    ExitTime       = cmdRes.ExitTime,
                    RunTime        = cmdRes.RunTime,
                    Log            = ReadLog(expectedLogPath),
                    ResultFilePath = File.Exists(expectedResultFilePath) ? expectedResultFilePath : null
                };
            }
            catch (Exception ex) {
                res = new ConversionResult()
                {
                    StdErr         = stdErrBuffer.ToString(),
                    StdOut         = stdOutBuffer.ToString(),
                    Message        = ex.Message,
                    Log            = ReadLog(expectedLogPath),
                    ResultFilePath = File.Exists(expectedResultFilePath) ? expectedResultFilePath : null
                };
            }
            return(res);
        }
Exemple #16
0
        private static async Task ExecuteInternal(Action <ArgumentsBuilder> configure, CancellationToken cancellationToken)
        {
            ThrowIfNull(ToolPath, nameof(SdkManager));

            var stdErrBuffer = new StringBuilder();
            await Cli.Wrap(ToolPath)
            .WithArguments(configure)
            .WithStandardErrorPipe(PipeTarget.ToStringBuilder(stdErrBuffer))
            .WithStandardOutputPipe(PipeTarget.ToDelegate(l => Logger.WriteLine(l, LogLevel.Detailed)))
            .WithStandardInputPipe(PipeSource.FromString("y"))
            .ExecuteAsync(cancellationToken);

            var stdErr = stdErrBuffer.ToString().Trim();

            if (!string.IsNullOrEmpty(stdErr))
            {
                throw new Exception(stdErr);
            }
        }
Exemple #17
0
        internal static async Task <string> ExecuteInternal(Action <ArgumentsBuilder> configure, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(null);
            }

            var toolPath = ToolPath;
            var builder  = new ArgumentsBuilder();

            configure(builder);
            var args = builder.Build();

            Logger.WriteLine($"{toolPath} {args}", LogLevel.Normal);
            var stdErrBuffer = new StringBuilder();
            var stdOutBuffer = new StringBuilder();
            var stdOut       = PipeTarget.Merge(PipeTarget.ToStringBuilder(stdOutBuffer),
                                                PipeTarget.ToDelegate(l => Logger.WriteLine(l, LogLevel.Verbose)));

            var result = await Cli.Wrap(toolPath)
                         .WithArguments(args)
                         .WithValidation(CommandResultValidation.None)
                         .WithStandardErrorPipe(PipeTarget.ToStringBuilder(stdErrBuffer))
                         .WithStandardOutputPipe(stdOut)
                         .ExecuteAsync(cancellationToken);

            var stdErr = stdErrBuffer.ToString().Trim();

            if (!string.IsNullOrEmpty(stdErr))
            {
                if (stdErr.Split('\n').Select(x => x.Trim()).All(x => x.StartsWith("Warning:", StringComparison.InvariantCultureIgnoreCase)))
                {
                    Logger.WriteWarning(stdErr);
                }
                else
                {
                    throw new Exception(stdErr);
                }
            }

            return(stdOutBuffer.ToString().Trim());
        }
        public async Task <string> Compress(string file, string directory, CancellationToken ct)
        {
            var resultFile = GetResultFile(file);

            var stderr = new StringBuilder();
            var cmd    = Cli.Wrap("ffmpeg")
                         .WithArguments($"-y -i \"{file}\" -ac 1 -c:a libopus -af \"highpass=f=200,lowpass=f=4000\" -ar 16000 -b:a 8K -vbr constrained \"{resultFile}\"")
                         .WithWorkingDirectory(directory)
                         .WithStandardErrorPipe(PipeTarget.ToStringBuilder(stderr));

            try
            {
                await cmd.ExecuteAsync(ct);
            } catch (Exception ex)
            {
                throw new Exception(stderr.ToString(), ex);
            }


            return(Path.GetFileName(resultFile));
        }
        public override async Task <ExecutionResult> RunAsync(IStepExecutionContext context)
        {
            // It's important that the CHROM names match (NC_000962.3) else it will report 0
            var ouput = Session.CreateFolder();

            Output = ouput.GetFile("output");
            var errorBuilder = new StringBuilder();
            var command      = Cli
                               .Wrap("bedtools")
                               .WithArguments(args => args
                                              .Add("coverage")
                                              .Add("-a")
                                              .Add(FileA.AbsolutePath)
                                              .Add("-b")
                                              .Add(FileB.AbsolutePath))
                               .WithStandardOutputPipe(PipeTarget.ToFile(Output.AbsolutePath))
                               .WithStandardErrorPipe(PipeTarget.ToStringBuilder(errorBuilder));

            await command.ExecuteAsync();

            return(ExecutionResult.Next());
        }
Exemple #20
0
    public IEnumerable <GitCommit> ForRepository(IAnalysisLocation analysisLocation, string gitPath)
    {
        var stdErrBuffer = new StringBuilder();
        var stdOutBuffer = new StringBuilder();
        var command      = CliWrap.Cli.Wrap(gitPath).WithArguments(
            args => args
            .Add("log")
            // Commit hash, author date, strict ISO 8601 format
            // Lists commits as '583d813db3e28b9b44a29db352e2f0e1b4c6e420 2021-05-19T15:24:24-04:00'
            // Source: https://git-scm.com/docs/pretty-formats
            .Add("--pretty=format:%H %aI")
            )
                           .WithValidation(CommandResultValidation.None)
                           .WithWorkingDirectory(analysisLocation.Path)
                           .WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdOutBuffer))
                           .WithStandardErrorPipe(PipeTarget.ToStringBuilder(stdErrBuffer));

        using var task = command.ExecuteAsync().Task;
        task.Wait();

        if (task.Result.ExitCode != 0)
        {
            throw new GitException($"{CliOutput.Exception_Git_EncounteredError}\n{stdErrBuffer}");
        }

        var commitsWithDates = stdOutBuffer.ToString().Split("\n");
        var commits          = new List <GitCommit>();

        foreach (var commitAndDate in commitsWithDates)
        {
            var separated = commitAndDate.Split(" ");
            commits.Add(new GitCommit(
                            separated[0],
                            DateTimeOffset.ParseExact(separated[1], "yyyy'-'MM'-'dd'T'HH':'mm':'ssK", null)
                            ));
        }

        return(commits);
    }