cmCTestStartCommand.cxx 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file LICENSE.rst or https://cmake.org/licensing for details. */
  3. #include "cmCTestStartCommand.h"
  4. #include <cstddef>
  5. #include <sstream>
  6. #include <vector>
  7. #include "cmCTest.h"
  8. #include "cmCTestVC.h"
  9. #include "cmExecutionStatus.h"
  10. #include "cmGeneratedFileStream.h"
  11. #include "cmMakefile.h"
  12. #include "cmStringAlgorithms.h"
  13. #include "cmSystemTools.h"
  14. #include "cmValue.h"
  15. bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
  16. cmExecutionStatus& status) const
  17. {
  18. if (args.empty()) {
  19. status.SetError("called with incorrect number of arguments");
  20. return false;
  21. }
  22. size_t cnt = 0;
  23. bool append = false;
  24. bool quiet = false;
  25. char const* smodel = nullptr;
  26. cmValue src_dir;
  27. cmValue bld_dir;
  28. while (cnt < args.size()) {
  29. if (args[cnt] == "GROUP" || args[cnt] == "TRACK") {
  30. cnt++;
  31. if (cnt >= args.size() || args[cnt] == "APPEND" ||
  32. args[cnt] == "QUIET") {
  33. std::ostringstream e;
  34. e << args[cnt - 1] << " argument missing group name";
  35. status.SetError(e.str());
  36. return false;
  37. }
  38. this->CTest->SetSpecificGroup(args[cnt].c_str());
  39. cnt++;
  40. } else if (args[cnt] == "APPEND") {
  41. cnt++;
  42. append = true;
  43. } else if (args[cnt] == "QUIET") {
  44. cnt++;
  45. quiet = true;
  46. } else if (!smodel) {
  47. smodel = args[cnt].c_str();
  48. cnt++;
  49. } else if (!src_dir) {
  50. src_dir = cmValue(args[cnt]);
  51. cnt++;
  52. } else if (!bld_dir) {
  53. bld_dir = cmValue(args[cnt]);
  54. cnt++;
  55. } else {
  56. status.SetError("Too many arguments");
  57. return false;
  58. }
  59. }
  60. cmMakefile& mf = status.GetMakefile();
  61. if (!src_dir) {
  62. src_dir = mf.GetDefinition("CTEST_SOURCE_DIRECTORY");
  63. }
  64. if (!bld_dir) {
  65. bld_dir = mf.GetDefinition("CTEST_BINARY_DIRECTORY");
  66. }
  67. if (!src_dir) {
  68. status.SetError("source directory not specified. Specify source directory "
  69. "as an argument or set CTEST_SOURCE_DIRECTORY");
  70. return false;
  71. }
  72. if (!bld_dir) {
  73. status.SetError("binary directory not specified. Specify binary directory "
  74. "as an argument or set CTEST_BINARY_DIRECTORY");
  75. return false;
  76. }
  77. if (!smodel && !append) {
  78. status.SetError(
  79. "no test model specified and APPEND not specified. Specify "
  80. "either a test model or the APPEND argument");
  81. return false;
  82. }
  83. this->CTest->EmptyCTestConfiguration();
  84. std::string sourceDir = cmSystemTools::CollapseFullPath(*src_dir);
  85. std::string binaryDir = cmSystemTools::CollapseFullPath(*bld_dir);
  86. this->CTest->SetCTestConfiguration("SourceDirectory", sourceDir, quiet);
  87. this->CTest->SetCTestConfiguration("BuildDirectory", binaryDir, quiet);
  88. if (smodel) {
  89. cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
  90. "Run dashboard with model "
  91. << smodel << std::endl
  92. << " Source directory: " << *src_dir << std::endl
  93. << " Build directory: " << *bld_dir << std::endl,
  94. quiet);
  95. } else {
  96. cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
  97. "Run dashboard with "
  98. "to-be-determined model"
  99. << std::endl
  100. << " Source directory: " << *src_dir << std::endl
  101. << " Build directory: " << *bld_dir << std::endl,
  102. quiet);
  103. }
  104. char const* group = this->CTest->GetSpecificGroup();
  105. if (group) {
  106. cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
  107. " Group: " << group << std::endl, quiet);
  108. }
  109. // Log startup actions.
  110. std::string startLogFile = binaryDir + "/Testing/Temporary/LastStart.log";
  111. cmGeneratedFileStream ofs(startLogFile);
  112. if (!ofs) {
  113. cmCTestLog(this->CTest, ERROR_MESSAGE,
  114. "Cannot create log file: LastStart.log" << std::endl);
  115. return false;
  116. }
  117. // Make sure the source directory exists.
  118. if (!this->InitialCheckout(ofs, sourceDir, status)) {
  119. return false;
  120. }
  121. if (!cmSystemTools::FileIsDirectory(sourceDir)) {
  122. std::ostringstream e;
  123. e << "given source path\n"
  124. << " " << sourceDir << "\n"
  125. << "which is not an existing directory. "
  126. << "Set CTEST_CHECKOUT_COMMAND to a command line to create it.";
  127. status.SetError(e.str());
  128. return false;
  129. }
  130. int model;
  131. if (smodel) {
  132. model = cmCTest::GetTestModelFromString(smodel);
  133. } else {
  134. model = cmCTest::UNKNOWN;
  135. }
  136. this->CTest->SetTestModel(model);
  137. this->CTest->SetProduceXML(true);
  138. std::string fname;
  139. std::string src_dir_fname = cmStrCat(sourceDir, "/CTestConfig.cmake");
  140. cmSystemTools::ConvertToUnixSlashes(src_dir_fname);
  141. std::string bld_dir_fname = cmStrCat(binaryDir, "/CTestConfig.cmake");
  142. cmSystemTools::ConvertToUnixSlashes(bld_dir_fname);
  143. if (cmSystemTools::FileExists(bld_dir_fname)) {
  144. fname = bld_dir_fname;
  145. } else if (cmSystemTools::FileExists(src_dir_fname)) {
  146. fname = src_dir_fname;
  147. }
  148. if (!fname.empty()) {
  149. cmCTestOptionalLog(
  150. this->CTest, OUTPUT,
  151. " Reading ctest configuration file: " << fname << std::endl, quiet);
  152. bool readit = mf.ReadDependentFile(fname);
  153. if (!readit) {
  154. std::string m = cmStrCat("Could not find include file: ", fname);
  155. status.SetError(m);
  156. return false;
  157. }
  158. }
  159. this->CTest->SetCTestConfigurationFromCMakeVariable(
  160. &mf, "NightlyStartTime", "CTEST_NIGHTLY_START_TIME", quiet);
  161. this->CTest->SetCTestConfigurationFromCMakeVariable(&mf, "Site",
  162. "CTEST_SITE", quiet);
  163. this->CTest->SetCTestConfigurationFromCMakeVariable(
  164. &mf, "BuildName", "CTEST_BUILD_NAME", quiet);
  165. this->CTest->Initialize(binaryDir);
  166. cmCTestOptionalLog(
  167. this->CTest, OUTPUT,
  168. " Site: " << this->CTest->GetCTestConfiguration("Site") << std::endl
  169. << " Build name: "
  170. << cmCTest::SafeBuildIdField(
  171. this->CTest->GetCTestConfiguration("BuildName"))
  172. << std::endl,
  173. quiet);
  174. if (this->CTest->GetTestModel() == cmCTest::NIGHTLY &&
  175. this->CTest->GetCTestConfiguration("NightlyStartTime").empty()) {
  176. cmCTestOptionalLog(
  177. this->CTest, WARNING,
  178. "WARNING: No nightly start time found please set in CTestConfig.cmake"
  179. " or DartConfig.cmake"
  180. << std::endl,
  181. quiet);
  182. return false;
  183. }
  184. this->CTest->ReadCustomConfigurationFileTree(bld_dir, &mf);
  185. if (append) {
  186. if (!this->CTest->ReadExistingTag(quiet)) {
  187. return false;
  188. }
  189. } else {
  190. if (!this->CTest->CreateNewTag(quiet)) {
  191. return false;
  192. }
  193. }
  194. cmCTestOptionalLog(this->CTest, OUTPUT,
  195. " Use " << this->CTest->GetTestGroupString() << " tag: "
  196. << this->CTest->GetCurrentTag() << std::endl,
  197. quiet);
  198. return true;
  199. }
  200. bool cmCTestStartCommand::InitialCheckout(std::ostream& ofs,
  201. std::string const& sourceDir,
  202. cmExecutionStatus& status) const
  203. {
  204. cmMakefile& mf = status.GetMakefile();
  205. // Use the user-provided command to create the source tree.
  206. cmValue initialCheckoutCommand = mf.GetDefinition("CTEST_CHECKOUT_COMMAND");
  207. if (!initialCheckoutCommand) {
  208. initialCheckoutCommand = mf.GetDefinition("CTEST_CVS_CHECKOUT");
  209. }
  210. if (initialCheckoutCommand) {
  211. // Use a generic VC object to run and log the command.
  212. cmCTestVC vc(this->CTest, &mf, ofs);
  213. vc.SetSourceDirectory(sourceDir);
  214. if (!vc.InitialCheckout(*initialCheckoutCommand)) {
  215. return false;
  216. }
  217. }
  218. return true;
  219. }