/project/core/sourcecontrol/RobocopySourceControl.cs

https://github.com/psgirard/CruiseControl.NET · C# · 178 lines · 71 code · 26 blank · 81 comment · 1 complexity · 772ee9b7f1adc40ab836438c148baff3 MD5 · raw file

  1. using System.Diagnostics;
  2. using Exortech.NetReflector;
  3. using ThoughtWorks.CruiseControl.Core.Util;
  4. namespace ThoughtWorks.CruiseControl.Core.Sourcecontrol
  5. {
  6. /// <summary>
  7. /// <para>
  8. /// Uses RoboCopy as Source Control.
  9. /// </para>
  10. /// </summary>
  11. /// <title>RoboCopy Source Control Block</title>
  12. /// <version>1.4.4</version>
  13. /// <key name="type">
  14. /// <description>The type of source control block.</description>
  15. /// <value>robocopy</value>
  16. /// </key>
  17. /// <example>
  18. /// <code>
  19. /// &lt;sourcecontrol type="robocopy"&gt;
  20. /// &lt;repositoryRoot&gt;C:\Somewhere&lt;/repositoryRoot&gt;
  21. /// &lt;/sourcecontrol&gt;
  22. /// </code>
  23. /// </example>
  24. [ReflectorType("robocopy")]
  25. public class RobocopySourceControl : ProcessSourceControl
  26. {
  27. private static int[] GenerateExitCodes()
  28. {
  29. int[] exitCodes = new int[4];
  30. exitCodes[0] = 0; // All OK, nothing to do
  31. exitCodes[1] = 1; // Some files copied
  32. exitCodes[2] = 2; // Some extra files in destination tree
  33. exitCodes[3] = 3; // Copied and some extra files in destination tree
  34. // Note that we COULD want to have 4-7 as valid success codes, but i've not been
  35. // able to cause them to occur yet and so havent included them here.
  36. return exitCodes;
  37. }
  38. private static readonly int[] successExitCodes = GenerateExitCodes();
  39. /// <summary>
  40. /// Initializes a new instance of the <see cref="RobocopySourceControl" /> class.
  41. /// </summary>
  42. /// <remarks></remarks>
  43. public RobocopySourceControl() : this(new RobocopyHistoryParser(), new ProcessExecutor())
  44. {}
  45. /// <summary>
  46. /// Initializes a new instance of the <see cref="RobocopySourceControl" /> class.
  47. /// </summary>
  48. /// <param name="parser">The parser.</param>
  49. /// <param name="executor">The executor.</param>
  50. /// <remarks></remarks>
  51. public RobocopySourceControl(IHistoryParser parser, ProcessExecutor executor)
  52. : base(parser, executor)
  53. {
  54. this.Executable = "C:\\Windows\\System32\\robocopy.exe";
  55. this.AutoGetSource = false;
  56. this.WorkingDirectory = string.Empty;
  57. this.AdditionalArguments = string.Empty;
  58. }
  59. /// <summary>
  60. /// The executable location.
  61. /// </summary>
  62. /// <version>1.4.4</version>
  63. /// <default>C:\\Windows\\System32\\robocopy.exe</default>
  64. [ReflectorProperty("executable", Required = false)]
  65. public string Executable { get; set; }
  66. /// <summary>
  67. /// The repository root.
  68. /// </summary>
  69. /// <version>1.4.4</version>
  70. /// <default>n/a</default>
  71. [ReflectorProperty("repositoryRoot")]
  72. public string RepositoryRoot { get; set; }
  73. /// <summary>
  74. /// Whether to automatically get the source.
  75. /// </summary>
  76. /// <version>1.4.4</version>
  77. /// <default>false</default>
  78. [ReflectorProperty("autoGetSource", Required = false)]
  79. public bool AutoGetSource { get; set; }
  80. /// <summary>
  81. /// The working directory to use.
  82. /// </summary>
  83. /// <version>1.4.4</version>
  84. /// <default>Project Working Directory</default>
  85. [ReflectorProperty("workingDirectory", Required = false)]
  86. public string WorkingDirectory { get; set; }
  87. /// <summary>
  88. /// Any additional arguments.
  89. /// </summary>
  90. /// <version>1.4.4</version>
  91. /// <default>None</default>
  92. [ReflectorProperty("additionalArguments", Required = false)]
  93. public string AdditionalArguments { get; set; }
  94. /// <summary>
  95. /// Gets the modifications.
  96. /// </summary>
  97. /// <param name="from">From.</param>
  98. /// <param name="to">To.</param>
  99. /// <returns></returns>
  100. /// <remarks></remarks>
  101. public override Modification[] GetModifications(IIntegrationResult from, IIntegrationResult to)
  102. {
  103. string destinationDirectory = from.BaseFromWorkingDirectory(WorkingDirectory);
  104. ProcessArgumentBuilder builder = new ProcessArgumentBuilder();
  105. AddStandardArguments(builder, destinationDirectory);
  106. builder.AddArgument("/L");
  107. Modification[] modifications = GetModifications(new ProcessInfo(Executable, builder.ToString(), null, ProcessPriorityClass.Normal, successExitCodes), from.StartTime, to.StartTime);
  108. return modifications;
  109. }
  110. /// <summary>
  111. /// Labels the source control.
  112. /// </summary>
  113. /// <param name="result">The result.</param>
  114. /// <remarks></remarks>
  115. public override void LabelSourceControl(IIntegrationResult result)
  116. {}
  117. /// <summary>
  118. /// Gets the source.
  119. /// </summary>
  120. /// <param name="result">The result.</param>
  121. /// <remarks></remarks>
  122. public override void GetSource(IIntegrationResult result)
  123. {
  124. if (AutoGetSource)
  125. {
  126. string destinationDirectory = result.BaseFromWorkingDirectory(WorkingDirectory);
  127. ProcessArgumentBuilder builder = new ProcessArgumentBuilder();
  128. AddStandardArguments(builder, destinationDirectory);
  129. Execute(new ProcessInfo(Executable, builder.ToString(), null, ProcessPriorityClass.Normal, successExitCodes));
  130. }
  131. }
  132. // /MIR - MIRror a directory tree (equivalent to /E plus /PURGE).
  133. // /NP - No Progress - don't display % copied.
  134. // /X - Report all eXtra files, not just those selected.
  135. // /TS - Include source file Time Stamps in the output.
  136. // /FP - Include Full Pathname of files in the output.
  137. // /NDL - No Directory List - don't log directory names.
  138. // /NS - No Size - don't log file sizes.
  139. // /NJH - No Job Header.
  140. // /NJS - No Job Summary.
  141. private readonly static string standardArguments = " /MIR /NP /X /TS /FP /NDL /NS /NJH /NJS ";
  142. private void AddStandardArguments(
  143. ProcessArgumentBuilder builder,
  144. string destinationDirectory)
  145. {
  146. builder.AddArgument(RepositoryRoot);
  147. builder.AddArgument(destinationDirectory);
  148. builder.Append(standardArguments);
  149. builder.Append(AdditionalArguments);
  150. }
  151. }
  152. }