PageRenderTime 52ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/MSBuildVersioning/SourceControlInfoProvider.cs

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