Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / CTest / cmCTestUpdateHandler.cxx
blobc61078cf28e4d0e991adcd9ddeb0e69a0f51e66a
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCTestUpdateHandler.cxx,v $
5 Language: C++
6 Date: $Date: 2009-03-20 18:19:56 $
7 Version: $Revision: 1.64 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
18 #include "cmCTestUpdateHandler.h"
20 #include "cmCTest.h"
21 #include "cmake.h"
22 #include "cmMakefile.h"
23 #include "cmLocalGenerator.h"
24 #include "cmGlobalGenerator.h"
25 #include "cmVersion.h"
26 #include "cmGeneratedFileStream.h"
27 #include "cmXMLParser.h"
28 #include "cmXMLSafe.h"
30 #include "cmCTestVC.h"
31 #include "cmCTestCVS.h"
32 #include "cmCTestSVN.h"
34 #include <cmsys/auto_ptr.hxx>
36 //#include <cmsys/RegularExpression.hxx>
37 #include <cmsys/Process.h>
39 // used for sleep
40 #ifdef _WIN32
41 #include "windows.h"
42 #endif
44 #include <stdlib.h>
45 #include <math.h>
46 #include <float.h>
48 //----------------------------------------------------------------------
49 static const char* cmCTestUpdateHandlerUpdateStrings[] =
51 "Unknown",
52 "CVS",
53 "SVN"
56 static const char* cmCTestUpdateHandlerUpdateToString(int type)
58 if ( type < cmCTestUpdateHandler::e_UNKNOWN ||
59 type >= cmCTestUpdateHandler::e_LAST )
61 return cmCTestUpdateHandlerUpdateStrings[cmCTestUpdateHandler::e_UNKNOWN];
63 return cmCTestUpdateHandlerUpdateStrings[type];
66 class cmCTestUpdateHandlerLocale
68 public:
69 cmCTestUpdateHandlerLocale();
70 ~cmCTestUpdateHandlerLocale();
71 private:
72 std::string saveLCMessages;
75 cmCTestUpdateHandlerLocale::cmCTestUpdateHandlerLocale()
77 const char* lcmess = cmSystemTools::GetEnv("LC_MESSAGES");
78 if(lcmess)
80 saveLCMessages = lcmess;
82 // if LC_MESSAGES is not set to C, then
83 // set it, so that svn/cvs info will be in english ascii
84 if(! (lcmess && strcmp(lcmess, "C") == 0))
86 cmSystemTools::PutEnv("LC_MESSAGES=C");
90 cmCTestUpdateHandlerLocale::~cmCTestUpdateHandlerLocale()
92 // restore the value of LC_MESSAGES after running the version control
93 // commands
94 if(saveLCMessages.size())
96 std::string put = "LC_MESSAGES=";
97 put += saveLCMessages;
98 cmSystemTools::PutEnv(put.c_str());
100 else
102 cmSystemTools::UnsetEnv("LC_MESSAGES");
106 //----------------------------------------------------------------------
107 cmCTestUpdateHandler::cmCTestUpdateHandler()
111 //----------------------------------------------------------------------
112 void cmCTestUpdateHandler::Initialize()
114 this->Superclass::Initialize();
115 this->UpdateCommand = "";
116 this->UpdateType = e_CVS;
119 //----------------------------------------------------------------------
120 int cmCTestUpdateHandler::DetermineType(const char* cmd, const char* type)
122 cmCTestLog(this->CTest, DEBUG, "Determine update type from command: " << cmd
123 << " and type: " << type << std::endl);
124 if ( type && *type )
126 cmCTestLog(this->CTest, DEBUG, "Type specified: " << type << std::endl);
127 std::string stype = cmSystemTools::LowerCase(type);
128 if ( stype.find("cvs") != std::string::npos )
130 return cmCTestUpdateHandler::e_CVS;
132 if ( stype.find("svn") != std::string::npos )
134 return cmCTestUpdateHandler::e_SVN;
137 else
139 cmCTestLog(this->CTest, DEBUG, "Type not specified, check command: "
140 << cmd << std::endl);
141 std::string stype = cmSystemTools::LowerCase(cmd);
142 if ( stype.find("cvs") != std::string::npos )
144 return cmCTestUpdateHandler::e_CVS;
146 if ( stype.find("svn") != std::string::npos )
148 return cmCTestUpdateHandler::e_SVN;
151 return cmCTestUpdateHandler::e_UNKNOWN;
154 //----------------------------------------------------------------------
155 //clearly it would be nice if this were broken up into a few smaller
156 //functions and commented...
157 int cmCTestUpdateHandler::ProcessHandler()
159 // Make sure VCS tool messages are in English so we can parse them.
160 cmCTestUpdateHandlerLocale fixLocale;
161 static_cast<void>(fixLocale);
163 // Get source dir
164 const char* sourceDirectory = this->GetOption("SourceDirectory");
165 if ( !sourceDirectory )
167 cmCTestLog(this->CTest, ERROR_MESSAGE,
168 "Cannot find SourceDirectory key in the DartConfiguration.tcl"
169 << std::endl);
170 return -1;
173 cmGeneratedFileStream ofs;
174 if ( !this->CTest->GetShowOnly() )
176 this->StartLogFile("Update", ofs);
179 cmCTestLog(this->CTest, HANDLER_OUTPUT,
180 "Updating the repository" << std::endl);
182 // Make sure the source directory exists.
183 if(!this->InitialCheckout(ofs))
185 return -1;
188 cmCTestLog(this->CTest, HANDLER_OUTPUT, " Updating the repository: "
189 << sourceDirectory << std::endl);
191 if(!this->SelectVCS())
193 return -1;
196 cmCTestLog(this->CTest, HANDLER_OUTPUT, " Use "
197 << cmCTestUpdateHandlerUpdateToString(this->UpdateType)
198 << " repository type"
199 << std::endl;);
201 // Create an object to interact with the VCS tool.
202 cmsys::auto_ptr<cmCTestVC> vc;
203 switch (this->UpdateType)
205 case e_CVS: vc.reset(new cmCTestCVS(this->CTest, ofs)); break;
206 case e_SVN: vc.reset(new cmCTestSVN(this->CTest, ofs)); break;
207 default: vc.reset(new cmCTestVC(this->CTest, ofs)); break;
209 vc->SetCommandLineTool(this->UpdateCommand);
210 vc->SetSourceDirectory(sourceDirectory);
212 // Cleanup the working tree.
213 vc->Cleanup();
216 // Now update repository and remember what files were updated
218 cmGeneratedFileStream os;
219 if(!this->StartResultingXML(cmCTest::PartUpdate, "Update", os))
221 cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open log file"
222 << std::endl);
223 return -1;
225 std::string start_time = this->CTest->CurrentTime();
226 unsigned int start_time_time =
227 static_cast<unsigned int>(cmSystemTools::GetTime());
228 double elapsed_time_start = cmSystemTools::GetTime();
230 bool updated = vc->Update();
232 os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
233 << "<Update mode=\"Client\" Generator=\"ctest-"
234 << cmVersion::GetCMakeVersion() << "\">\n"
235 << "\t<Site>" << this->CTest->GetCTestConfiguration("Site") << "</Site>\n"
236 << "\t<BuildName>" << this->CTest->GetCTestConfiguration("BuildName")
237 << "</BuildName>\n"
238 << "\t<BuildStamp>" << this->CTest->GetCurrentTag() << "-"
239 << this->CTest->GetTestModelString() << "</BuildStamp>" << std::endl;
240 os << "\t<StartDateTime>" << start_time << "</StartDateTime>\n"
241 << "\t<StartTime>" << start_time_time << "</StartTime>\n"
242 << "\t<UpdateCommand>" << cmXMLSafe(vc->GetUpdateCommandLine())
243 << "</UpdateCommand>\n"
244 << "\t<UpdateType>" << cmXMLSafe(
245 cmCTestUpdateHandlerUpdateToString(this->UpdateType))
246 << "</UpdateType>\n";
248 vc->WriteXML(os);
250 int localModifications = 0;
251 int numUpdated = vc->GetPathCount(cmCTestVC::PathUpdated);
252 if(numUpdated)
254 cmCTestLog(this->CTest, HANDLER_OUTPUT,
255 " Found " << numUpdated << " updated files\n");
257 if(int numModified = vc->GetPathCount(cmCTestVC::PathModified))
259 cmCTestLog(this->CTest, HANDLER_OUTPUT,
260 " Found " << numModified << " locally modified files\n");
261 localModifications += numModified;
263 if(int numConflicting = vc->GetPathCount(cmCTestVC::PathConflicting))
265 cmCTestLog(this->CTest, HANDLER_OUTPUT,
266 " Found " << numConflicting << " conflicting files\n");
267 localModifications += numConflicting;
270 cmCTestLog(this->CTest, DEBUG, "End" << std::endl);
271 std::string end_time = this->CTest->CurrentTime();
272 os << "\t<EndDateTime>" << end_time << "</EndDateTime>\n"
273 << "\t<EndTime>" << static_cast<unsigned int>(cmSystemTools::GetTime())
274 << "</EndTime>\n"
275 << "<ElapsedMinutes>" <<
276 static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
277 << "</ElapsedMinutes>\n"
278 << "\t<UpdateReturnStatus>";
279 if(localModifications)
281 os << "Update error: There are modified or conflicting files in the "
282 "repository";
283 cmCTestLog(this->CTest, ERROR_MESSAGE,
284 " There are modified or conflicting files in the repository"
285 << std::endl);
287 if(!updated)
289 cmCTestLog(this->CTest, ERROR_MESSAGE, " Update command failed: "
290 << vc->GetUpdateCommandLine() << "\n");
292 os << "</UpdateReturnStatus>" << std::endl;
293 os << "</Update>" << std::endl;
294 return numUpdated;
297 //----------------------------------------------------------------------
298 bool cmCTestUpdateHandler::InitialCheckout(std::ostream& ofs)
300 // Use the user-provided command to create the source tree.
301 if(const char* command = this->GetOption("InitialCheckout"))
303 // Use a generic VC object to run and log the command.
304 cmCTestVC vc(this->CTest, ofs);
305 vc.SetSourceDirectory(this->GetOption("SourceDirectory"));
306 if(!vc.InitialCheckout(command))
308 return false;
311 if(!this->CTest->InitializeFromCommand(this->Command))
313 cmCTestLog(this->CTest, HANDLER_OUTPUT,
314 " Fatal Error in initialize: "
315 << std::endl);
316 cmSystemTools::SetFatalErrorOccured();
317 return false;
320 return true;
323 //----------------------------------------------------------------------
324 int cmCTestUpdateHandler::DetectVCS(const char* dir)
326 std::string sourceDirectory = dir;
327 cmCTestLog(this->CTest, DEBUG, "Check directory: "
328 << sourceDirectory.c_str() << std::endl);
329 sourceDirectory += "/.svn";
330 if ( cmSystemTools::FileExists(sourceDirectory.c_str()) )
332 return cmCTestUpdateHandler::e_SVN;
334 sourceDirectory = dir;
335 sourceDirectory += "/CVS";
336 if ( cmSystemTools::FileExists(sourceDirectory.c_str()) )
338 return cmCTestUpdateHandler::e_CVS;
340 return cmCTestUpdateHandler::e_UNKNOWN;
343 //----------------------------------------------------------------------
344 bool cmCTestUpdateHandler::SelectVCS()
346 // Get update command
347 this->UpdateCommand = this->CTest->GetCTestConfiguration("UpdateCommand");
349 // Detect the VCS managing the source tree.
350 this->UpdateType = this->DetectVCS(this->GetOption("SourceDirectory"));
351 if (this->UpdateType == e_UNKNOWN)
353 // The source tree does not have a recognized VCS. Check the
354 // configuration value or command name.
355 this->UpdateType = this->DetermineType(this->UpdateCommand.c_str(),
356 this->CTest->GetCTestConfiguration("UpdateType").c_str());
359 // If no update command was specified, lookup one for this VCS tool.
360 if (this->UpdateCommand.empty())
362 const char* key = 0;
363 switch (this->UpdateType)
365 case e_CVS: key = "CVSCommand"; break;
366 case e_SVN: key = "SVNCommand"; break;
367 default: break;
369 if (key)
371 this->UpdateCommand = this->CTest->GetCTestConfiguration(key);
373 if (this->UpdateCommand.empty())
375 cmOStringStream e;
376 e << "Cannot find UpdateCommand ";
377 if (key)
379 e << "or " << key;
381 e << " configuration key.";
382 cmCTestLog(this->CTest, ERROR_MESSAGE, e.str() << std::endl);
383 return false;
387 return true;