| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 |
- /*=========================================================================
- Program: CMake - Cross-Platform Makefile Generator
- Module: $RCSfile$
- Language: C++
- Date: $Date$
- Version: $Revision$
- Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
- See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notices for more information.
- =========================================================================*/
- #include "cmCTestUpdateHandler.h"
- #include "cmCTest.h"
- #include "cmake.h"
- #include "cmMakefile.h"
- #include "cmLocalGenerator.h"
- #include "cmGlobalGenerator.h"
- //#include <cmsys/RegularExpression.hxx>
- #include <cmsys/Process.h>
- // used for sleep
- #ifdef _WIN32
- #include "windows.h"
- #endif
- #include <stdlib.h>
- #include <math.h>
- #include <float.h>
- //----------------------------------------------------------------------
- cmCTestUpdateHandler::cmCTestUpdateHandler()
- {
- m_Verbose = false;
- m_CTest = 0;
- }
- //----------------------------------------------------------------------
- //clearly it would be nice if this were broken up into a few smaller
- //functions and commented...
- int cmCTestUpdateHandler::UpdateDirectory(cmCTest *ctest_inst)
- {
- m_CTest = ctest_inst;
-
- int count = 0;
- std::string::size_type cc, kk;
- std::string cvsCommand = m_CTest->GetDartConfiguration("CVSCommand");
- if ( cvsCommand.size() == 0 )
- {
- std::cerr << "Cannot find CVSCommand key in the DartConfiguration.tcl" << std::endl;
- return -1;
- }
- std::string cvsOptions = m_CTest->GetDartConfiguration("CVSUpdateOptions");
- if ( cvsOptions.size() == 0 )
- {
- std::cerr << "Cannot find CVSUpdateOptions key in the DartConfiguration.tcl" << std::endl;
- return -1;
- }
- std::string sourceDirectory = m_CTest->GetDartConfiguration("SourceDirectory");
- if ( sourceDirectory.size() == 0 )
- {
- std::cerr << "Cannot find SourceDirectory key in the DartConfiguration.tcl" << std::endl;
- return -1;
- }
- std::string extra_update_opts;
- if ( m_CTest->GetTestModel() == cmCTest::NIGHTLY )
- {
- struct tm* t = cmCTest::GetNightlyTime(m_CTest->GetDartConfiguration("NightlyStartTime"),
- m_Verbose, m_CTest->GetTomorrowTag());
- char current_time[1024];
- sprintf(current_time, "%04d-%02d-%02d %02d:%02d:%02d UTC",
- t->tm_year + 1900,
- t->tm_mon + 1,
- t->tm_mday,
- t->tm_hour,
- t->tm_min,
- t->tm_sec);
- std::string today_update_date = current_time;
-
- extra_update_opts += "-D \"" + today_update_date +"\"";
- //std::cout << "Update: " << extra_update_opts << std::endl;
- }
- std::string command = cvsCommand + " -z3 update " + cvsOptions +
- " " + extra_update_opts;
- std::ofstream os;
- if ( !m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), "Update.xml", os) )
- {
- std::cerr << "Cannot open log file" << std::endl;
- }
- std::string start_time = m_CTest->CurrentTime();
- double elapsed_time_start = cmSystemTools::GetTime();
- std::string goutput;
- int retVal = 0;
- bool res = true;
- std::ofstream ofs;
- if ( !m_CTest->GetShowOnly() )
- {
- res = cmSystemTools::RunSingleCommand(command.c_str(), &goutput,
- &retVal, sourceDirectory.c_str(),
- m_Verbose, 0 /*m_TimeOut*/);
- if ( m_CTest->OpenOutputFile("Temporary", "LastUpdate.log", ofs) )
- {
- ofs << goutput << std::endl;;
- }
- }
- else
- {
- std::cout << "Update with command: " << command << std::endl;
- }
- os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- << "<Update mode=\"Client\" Generator=\"ctest-" << CMake_VERSION_FULL << "\">\n"
- << "\t<Site>" << m_CTest->GetDartConfiguration("Site") << "</Site>\n"
- << "\t<BuildName>" << m_CTest->GetDartConfiguration("BuildName")
- << "</BuildName>\n"
- << "\t<BuildStamp>" << m_CTest->GetCurrentTag() << "-"
- << m_CTest->GetTestModelString() << "</BuildStamp>" << std::endl;
- os << "\t<StartDateTime>" << start_time << "</StartDateTime>\n"
- << "\t<UpdateCommand>" << m_CTest->MakeXMLSafe(command)
- << "</UpdateCommand>\n"
- << "\t<UpdateReturnStatus>";
- int failed = 0;
- if ( !res || retVal )
- {
- os << "Update error: ";
- os << m_CTest->MakeXMLSafe(goutput);
- std::cerr << "Update with command: " << command << " failed" << std::endl;
- failed = 1;
- }
- os << "</UpdateReturnStatus>" << std::endl;
- if ( !failed )
- {
- std::vector<cmStdString> lines;
- cmSystemTools::Split(goutput.c_str(), lines);
- std::cout << "Updated; gathering version information" << std::endl;
- cmsys::RegularExpression date_author("^date: +([^;]+); +author: +([^;]+); +state: +[^;]+;");
- cmsys::RegularExpression revision("^revision +([^ ]*) *$");
- cmsys::RegularExpression end_of_file("^=============================================================================$");
- cmsys::RegularExpression end_of_comment("^----------------------------$");
- std::string current_path = "<no-path>";
- bool first_file = true;
- cmCTestUpdateHandler::AuthorsToUpdatesMap authors_files_map;
- int num_updated = 0;
- int num_modified = 0;
- int num_conflicting = 0;
- for ( cc= 0 ; cc < lines.size(); cc ++ )
- {
- const char* line = lines[cc].c_str();
- char mod = line[0];
- if ( line[1] == ' ' && mod != '?' )
- {
- if ( mod != 'M' && mod != 'C' )
- {
- count ++;
- }
- const char* file = line + 2;
- //std::cout << "Line" << cc << ": " << mod << " - " << file << std::endl;
- std::string logcommand = cvsCommand + " -z3 log -N " + file;
- //std::cout << "Do log: " << logcommand << std::endl;
- std::string output;
- res = cmSystemTools::RunSingleCommand(logcommand.c_str(), &output,
- &retVal, sourceDirectory.c_str(),
- m_Verbose, 0 /*m_TimeOut*/);
- if ( ofs )
- {
- ofs << output << std::endl;
- }
- if ( res && retVal == 0)
- {
- //std::cout << output << std::endl;
- std::vector<cmStdString> ulines;
- cmSystemTools::Split(output.c_str(), ulines);
- std::string::size_type sline = 0;
- std::string srevision1 = "Unknown";
- std::string sdate1 = "Unknown";
- std::string sauthor1 = "Unknown";
- std::string semail1 = "Unknown";
- std::string comment1 = "";
- std::string srevision2 = "Unknown";
- std::string sdate2 = "Unknown";
- std::string sauthor2 = "Unknown";
- std::string comment2 = "";
- std::string semail2 = "Unknown";
- bool have_first = false;
- bool have_second = false;
- for ( kk = 0; kk < ulines.size(); kk ++ )
- {
- const char* clp = ulines[kk].c_str();
- if ( !have_second && !sline && revision.find(clp) )
- {
- if ( !have_first )
- {
- srevision1 = revision.match(1);
- }
- else
- {
- srevision2 = revision.match(1);
- }
- }
- else if ( !have_second && !sline && date_author.find(clp) )
- {
- sline = kk + 1;
- if ( !have_first )
- {
- sdate1 = date_author.match(1);
- sauthor1 = date_author.match(2);
- }
- else
- {
- sdate2 = date_author.match(1);
- sauthor2 = date_author.match(2);
- }
- }
- else if ( sline && end_of_comment.find(clp) || end_of_file.find(clp))
- {
- if ( !have_first )
- {
- have_first = true;
- }
- else if ( !have_second )
- {
- have_second = true;
- }
- sline = 0;
- }
- else if ( sline )
- {
- if ( !have_first )
- {
- comment1 += clp;
- comment1 += "\n";
- }
- else
- {
- comment2 += clp;
- comment2 += "\n";
- }
- }
- }
- if ( mod == 'M' )
- {
- comment1 = "Locally modified file\n";
- }
- if ( mod == 'C' )
- {
- comment1 = "Conflict while updating\n";
- }
- std::string path = cmSystemTools::GetFilenamePath(file);
- std::string fname = cmSystemTools::GetFilenameName(file);
- if ( path != current_path )
- {
- if ( !first_file )
- {
- os << "\t</Directory>" << std::endl;
- }
- else
- {
- first_file = false;
- }
- os << "\t<Directory>\n"
- << "\t\t<Name>" << path << "</Name>" << std::endl;
- }
- if ( mod == 'C' )
- {
- num_conflicting ++;
- os << "\t<Conflicting>" << std::endl;
- }
- else if ( mod == 'M' )
- {
- num_modified ++;
- os << "\t<Modified>" << std::endl;
- }
- else
- {
- num_updated ++;
- os << "\t<Updated>" << std::endl;
- }
- if ( srevision2 == "Unknown" )
- {
- srevision2 = srevision1;
- }
- os << "\t\t<File Directory=\"" << path << "\">" << fname
- << "</File>\n"
- << "\t\t<Directory>" << path << "</Directory>\n"
- << "\t\t<FullName>" << file << "</FullName>\n"
- << "\t\t<CheckinDate>" << sdate1 << "</CheckinDate>\n"
- << "\t\t<Author>" << sauthor1 << "</Author>\n"
- << "\t\t<Email>" << semail1 << "</Email>\n"
- << "\t\t<Log>" << cmCTest::MakeXMLSafe(comment1) << "</Log>\n"
- << "\t\t<Revision>" << srevision1 << "</Revision>\n"
- << "\t\t<PriorRevision>" << srevision2 << "</PriorRevision>"
- << std::endl;
- if ( srevision2 != srevision1 )
- {
- os
- << "\t\t<Revisions>\n"
- << "\t\t\t<Revision>" << srevision1 << "</Revision>\n"
- << "\t\t\t<PreviousRevision>" << srevision2 << "</PreviousRevision>\n"
- << "\t\t\t<Author>" << sauthor1<< "</Author>\n"
- << "\t\t\t<Date>" << sdate1 << "</Date>\n"
- << "\t\t\t<Comment>" << cmCTest::MakeXMLSafe(comment1) << "</Comment>\n"
- << "\t\t\t<Email>" << semail1 << "</Email>\n"
- << "\t\t</Revisions>\n"
- << "\t\t<Revisions>\n"
- << "\t\t\t<Revision>" << srevision2 << "</Revision>\n"
- << "\t\t\t<PreviousRevision>" << srevision2 << "</PreviousRevision>\n"
- << "\t\t\t<Author>" << sauthor2<< "</Author>\n"
- << "\t\t\t<Date>" << sdate2 << "</Date>\n"
- << "\t\t\t<Comment>" << cmCTest::MakeXMLSafe(comment2) << "</Comment>\n"
- << "\t\t\t<Email>" << semail2 << "</Email>\n"
- << "\t\t</Revisions>" << std::endl;
- }
- if ( mod == 'C' )
- {
- os << "\t</Conflicting>" << std::endl;
- }
- else if ( mod == 'M' )
- {
- os << "\t</Modified>" << std::endl;
- }
- else
- {
- os << "\t</Updated>" << std::endl;
- }
- cmCTestUpdateHandler::UpdateFiles *u = &authors_files_map[sauthor1];
- cmCTestUpdateHandler::StringPair p;
- p.first = path;
- p.second = fname;
- u->push_back(p);
- current_path = path;
- }
- }
- }
- if ( num_updated )
- {
- std::cout << "Found " << num_updated << " updated files" << std::endl;
- }
- if ( num_modified )
- {
- std::cout << "Found " << num_modified << " locally modified files"
- << std::endl;
- }
- if ( num_conflicting )
- {
- std::cout << "Found " << num_conflicting << " conflicting files"
- << std::endl;
- }
- if ( !first_file )
- {
- os << "\t</Directory>" << std::endl;
- }
- cmCTestUpdateHandler::AuthorsToUpdatesMap::iterator it;
- for ( it = authors_files_map.begin();
- it != authors_files_map.end();
- it ++ )
- {
- os << "\t<Author>\n"
- << "\t\t<Name>" << it->first << "</Name>" << std::endl;
- cmCTestUpdateHandler::UpdateFiles *u = &(it->second);
- for ( cc = 0; cc < u->size(); cc ++ )
- {
- os << "\t\t<File Directory=\"" << (*u)[cc].first << "\">"
- << (*u)[cc].second << "</File>" << std::endl;
- }
- os << "\t</Author>" << std::endl;
- }
- }
- //std::cout << "End" << std::endl;
- std::string end_time = m_CTest->CurrentTime();
- os << "\t<EndDateTime>" << end_time << "</EndDateTime>\n"
- << "<ElapsedMinutes>" <<
- static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
- << "</ElapsedMinutes>"
- << "</Update>" << std::endl;
-
- if ( ofs )
- {
- ofs.close();
- }
- if (! res || retVal )
- {
- std::cerr << "Error(s) when updating the project" << std::endl;
- std::cerr << "Output: " << goutput << std::endl;
- return -1;
- }
- return count;
- }
|