<commit_before>using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace GitHub.Unity
{
    static class ProcessTaskExtensions
    {
        public static T Configure<T>(this T task, IProcessManager processManager, bool withInput = false)
            where T : IProcess
        {
            return processManager.Configure(task, withInput);
        }

        public static T Configure<T>(this T task, IProcessManager processManager, string executable, string arguments,
            NPath workingDirectory = null, bool withInput = false)
            where T : IProcess
        {
            return processManager.Configure(task, executable, arguments, workingDirectory, withInput);
        }
    }

    interface IProcess
    {
        void Configure(Process existingProcess);
        void Configure(ProcessStartInfo psi);
        event Action<string> OnErrorData;
        StreamWriter StandardInput { get; }
        int ProcessId { get; }
        string ProcessName { get; }
        string ProcessArguments { get; }
        Process Process { get; set; }
        event Action<IProcess> OnStartProcess;
        event Action<IProcess> OnEndProcess;
    }

    interface IProcessTask<T> : ITask<T>, IProcess
    {
        void Configure(ProcessStartInfo psi, IOutputProcessor<T> processor);
    }

    interface IProcessTask<TData, T> : ITask<TData, T>, IProcess
    {
        void Configure(ProcessStartInfo psi, IOutputProcessor<TData, T> processor);
    }

    class ProcessWrapper
    {
        private readonly IOutputProcessor outputProcessor;
        private readonly Action onStart;
        private readonly Action onEnd;
        private readonly Action<Exception, string> onError;
        private readonly CancellationToken token;
        private readonly List<string> errors = new List<string>();

        public Process Process { get; }
        public StreamWriter Input { get; private set; }

        private ILogging logger;
        protected ILogging Logger { get { return logger = logger ?? Logging.GetLogger(GetType()); } }

        public ProcessWrapper(Process process, IOutputProcessor outputProcessor,
            Action onStart, Action onEnd, Action<Exception, string> onError,
            CancellationToken token)
        {
            this.outputProcessor = outputProcessor;
            this.onStart = onStart;
            this.onEnd = onEnd;
            this.onError = onError;
            this.token = token;
            this.Process = process;
        }

        public void Run()
        {
            try
            {
                Process.Start();
            }
            catch (Win32Exception ex)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendLine("Error code " + ex.NativeErrorCode);
                if (ex.NativeErrorCode == 2)
                {
                    sb.AppendLine("The system cannot find the file specified.");
                }
                foreach (string env in Process.StartInfo.EnvironmentVariables.Keys)
                {
                    sb.AppendFormat("{0}:{1}", env, Process.StartInfo.EnvironmentVariables[env]);
                    sb.AppendLine();
                }
                onError?.Invoke(ex, String.Format("{0} {1}", ex.Message, sb.ToString()));
                onEnd?.Invoke();
                return;
            }

            if (Process.StartInfo.RedirectStandardInput)
                Input = new StreamWriter(Process.StandardInput.BaseStream, new UTF8Encoding(false));

            onStart?.Invoke();

            if (Process.StartInfo.CreateNoWindow)
            {
                if (Process.StartInfo.RedirectStandardOutput)
                {
                    var outputStream = Process.StandardOutput;
                    var line = outputStream.ReadLine();
                    while (line != null)
                    {
                        outputProcessor.LineReceived(line);

                        if (token.IsCancellationRequested)
                        {
                            if (!Process.HasExited)
                                Process.Kill();

                            Process.Close();
                            onEnd?.Invoke();
                            token.ThrowIfCancellationRequested();
                        }

                        line = outputStream.ReadLine();
                    }
                    outputProcessor.LineReceived(null);
                }

                if (!Process.StartInfo.RedirectStandardError)
                {
                    var errorStream = Process.StandardError;
                    var errorLine = errorStream.ReadLine();
                    while (errorLine != null)
                    {
                        errors.Add(errorLine);

                        if (token.IsCancellationRequested)
                        {
                            if (!Process.HasExited)
                                Process.Kill();

                            Process.Close();
                            onEnd?.Invoke();
                            token.ThrowIfCancellationRequested();
                        }

                        errorLine = errorStream.ReadLine();
                    }<commit_msg>Fixing error redirection<commit_after>using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace GitHub.Unity
{
    static class ProcessTaskExtensions
    {
        public static T Configure<T>(this T task, IProcessManager processManager, bool withInput = false)
            where T : IProcess
        {
            return processManager.Configure(task, withInput);
        }

        public static T Configure<T>(this T task, IProcessManager processManager, string executable, string arguments,
            NPath workingDirectory = null, bool withInput = false)
            where T : IProcess
        {
            return processManager.Configure(task, executable, arguments, workingDirectory, withInput);
        }
    }

    interface IProcess
    {
        void Configure(Process existingProcess);
        void Configure(ProcessStartInfo psi);
        event Action<string> OnErrorData;
        StreamWriter StandardInput { get; }
        int ProcessId { get; }
        string ProcessName { get; }
        string ProcessArguments { get; }
        Process Process { get; set; }
        event Action<IProcess> OnStartProcess;
        event Action<IProcess> OnEndProcess;
    }

    interface IProcessTask<T> : ITask<T>, IProcess
    {
        void Configure(ProcessStartInfo psi, IOutputProcessor<T> processor);
    }

    interface IProcessTask<TData, T> : ITask<TData, T>, IProcess
    {
        void Configure(ProcessStartInfo psi, IOutputProcessor<TData, T> processor);
    }

    class ProcessWrapper
    {
        private readonly IOutputProcessor outputProcessor;
        private readonly Action onStart;
        private readonly Action onEnd;
        private readonly Action<Exception, string> onError;
        private readonly CancellationToken token;

        public Process Process { get; }
        public StreamWriter Input { get; private set; }

        private ILogging logger;
        protected ILogging Logger { get { return logger = logger ?? Logging.GetLogger(GetType()); } }

        public ProcessWrapper(Process process, IOutputProcessor outputProcessor,
            Action onStart, Action onEnd, Action<Exception, string> onError,
            CancellationToken token)
        {
            this.outputProcessor = outputProcessor;
            this.onStart = onStart;
            this.onEnd = onEnd;
            this.onError = onError;
            this.token = token;
            this.Process = process;
        }

        public void Run()
        {
            try
            {
                Process.Start();
            }
            catch (Win32Exception ex)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendLine("Error code " + ex.NativeErrorCode);
                if (ex.NativeErrorCode == 2)
                {
                    sb.AppendLine("The system cannot find the file specified.");
                }
                foreach (string env in Process.StartInfo.EnvironmentVariables.Keys)
                {
                    sb.AppendFormat("{0}:{1}", env, Process.StartInfo.EnvironmentVariables[env]);
                    sb.AppendLine();
                }
                onError?.Invoke(ex, String.Format("{0} {1}", ex.Message, sb.ToString()));
                onEnd?.Invoke();
                return;
            }

            if (Process.StartInfo.RedirectStandardInput)
                Input = new StreamWriter(Process.StandardInput.BaseStream, new UTF8Encoding(false));

            var errors = new List<string>();

            onStart?.Invoke();
            if (Process.StartInfo.CreateNoWindow)
            {
                if (Process.StartInfo.RedirectStandardOutput)
                {
                    var outputStream = Process.StandardOutput;
                    var line = outputStream.ReadLine();
                    while (line != null)
                    {
                        outputProcessor.LineReceived(line);

                        if (token.IsCancellationRequested)
                        {
                            if (!Process.HasExited)
                                Process.Kill();

                            Process.Close();
                            onEnd?.Invoke();
                            token.ThrowIfCancellationRequested();
                        }

                        line = outputStream.ReadLine();
                    }
                    outputProcessor.LineReceived(null);
                }

                if (Process.StartInfo.RedirectStandardError)
                {
                    var errorStream = Process.StandardError;
                    var errorLine = errorStream.ReadLine();
                    while (errorLine != null)
                    {
                        errors.Add(errorLine);

                        if (token.IsCancellationRequested)
                        {
                            if (!Process.HasExited)
                                Process.Kill();

                            Process.Close();
                            onEnd?.Invoke();
                            token.ThrowIfCancellationRequested();
                        }

                        errorLine = errorStream.ReadLine();
                    }
{'fraction_non_alphanumeric': 0.0787511649580615, 'fraction_numerical': 0.0014911463187325257, 'mean_word_length': 1.4869061413673232, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6636211', 'n_tokens_mistral': 2504, 'n_tokens_neox': 2380, 'n_words': 584}