PageRenderTime 17ms CodeModel.GetById 11ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/MSBuildVersioning/SourceControlInfoProvider.cs

#
C# | 102 lines | 85 code | 13 blank | 4 comment | 15 complexity | 3ae2612719d3a2b8f0ee5186fac509f5 MD5 | raw file
  1using System;
  2using System.Collections.Generic;
  3using System.ComponentModel;
  4using System.Diagnostics;
  5using System.Text;
  6
  7namespace MSBuildVersioning
  8{
  9    /// <summary>
 10    /// Abstract class providing helper methods to execute and scrape information from source
 11    /// control command line programs.
 12    /// </summary>
 13    public abstract class SourceControlInfoProvider
 14    {
 15        protected SourceControlInfoProvider()
 16        {
 17            Path = String.Empty;
 18        }
 19
 20        public string Path { get; set; }
 21
 22        public abstract string SourceControlName { get; }
 23
 24        public bool IgnoreToolNotFound { get; set; }
 25
 26        protected virtual IList<string> ExecuteCommand(string fileName, string arguments)
 27        {
 28            return ExecuteCommand(fileName, arguments, null);
 29        }
 30
 31        protected virtual IList<string> ExecuteCommand(string fileName, string arguments, Func<int, string, bool> errorHandler)
 32        {
 33            IList<string> output = new List<string>();
 34            ExecuteCommand(fileName, arguments, outputLine => output.Add(outputLine), errorHandler);
 35            return output;
 36        }
 37
 38        protected virtual void ExecuteCommand(string fileName, string arguments,
 39            Action<string> outputHandler, Func<int, string, bool> errorHandler)
 40        {
 41            StringBuilder error = new StringBuilder();
 42
 43            using (Process process = new Process())
 44            {
 45                process.StartInfo.FileName = fileName;
 46                process.StartInfo.Arguments = arguments;
 47                process.StartInfo.WorkingDirectory = Path;
 48                process.StartInfo.CreateNoWindow = true;
 49                process.StartInfo.UseShellExecute = false;
 50                process.StartInfo.RedirectStandardOutput = true;
 51                process.StartInfo.RedirectStandardError = true;
 52
 53                process.OutputDataReceived += (o, e) =>
 54                    {
 55                        if (e.Data != null)
 56                            outputHandler(e.Data);
 57                    };
 58
 59                process.ErrorDataReceived += (o, e) =>
 60                    {
 61                        if (e.Data != null)
 62                            error.AppendLine(e.Data);
 63                    };
 64
 65                try
 66                {
 67                    process.Start();
 68                }
 69                catch (Win32Exception e)
 70                {
 71                    if (e.NativeErrorCode != 2 && e.NativeErrorCode != 267) // The system cannot find the file specified. || The directory name is invalid.
 72                    {
 73                        throw new BuildErrorException(String.Format(
 74                            "{0} command \"{1}\" with path \"{2}\" could not be started." + Environment.NewLine +
 75                            "Please ensure that {0} is installed. Error Code is {3}.",
 76                            SourceControlName, fileName, Path, e.NativeErrorCode));
 77                    }
 78                    if (IgnoreToolNotFound)
 79                    {
 80                        return;
 81                    }
 82                    throw new BuildErrorException(String.Format(
 83                        "{0} command \"{1}\" could not be found." + Environment.NewLine +
 84                        "Please ensure that {0} is installed. Error {2}.",
 85                        SourceControlName, fileName, e.NativeErrorCode));
 86                }
 87
 88                process.BeginOutputReadLine();
 89                process.BeginErrorReadLine();
 90                process.WaitForExit();
 91
 92                var reportError = errorHandler != null && errorHandler(process.ExitCode, error.ToString());
 93                if (reportError && (process.ExitCode != 0 || error.Length > 0))
 94                {
 95                    throw new BuildErrorException(String.Format(
 96                        "{0} command \"{1} {2}\" exited with code {3}.\n{4}",
 97                        SourceControlName, fileName, arguments, process.ExitCode, error));
 98                }
 99            }
100        }
101    }
102}