cmCTestStartCommand.cxx 7.7 KB

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