ENH: Factor global-VC parts out of cmCTestSVN

This factors parts of the svn update implementation that are useful for
any globally-versioning vcs tool into cmCTestGlobalVC.  It will allow
the code to be shared among the support classes for most vcs tools.
This commit is contained in:
Brad King 2009-04-22 09:18:19 -04:00
parent efe07c4e0a
commit d25289ad92
5 changed files with 213 additions and 114 deletions

View File

@ -355,6 +355,8 @@ SET(CTEST_SRCS cmCTest.cxx
CTest/cmCTestVC.cxx
CTest/cmCTestVC.h
CTest/cmCTestGlobalVC.cxx
CTest/cmCTestGlobalVC.h
CTest/cmCTestCVS.cxx
CTest/cmCTestCVS.h
CTest/cmCTestSVN.cxx

View File

@ -0,0 +1,132 @@
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc. 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 "cmCTestGlobalVC.h"
#include "cmCTest.h"
#include "cmSystemTools.h"
#include "cmXMLSafe.h"
#include <cmsys/RegularExpression.hxx>
//----------------------------------------------------------------------------
cmCTestGlobalVC::cmCTestGlobalVC(cmCTest* ct, std::ostream& log):
cmCTestVC(ct, log)
{
this->PriorRev = this->Unknown;
}
//----------------------------------------------------------------------------
cmCTestGlobalVC::~cmCTestGlobalVC()
{
}
//----------------------------------------------------------------------------
const char* cmCTestGlobalVC::LocalPath(std::string const& path)
{
return path.c_str();
}
//----------------------------------------------------------------------------
void cmCTestGlobalVC::DoRevision(Revision const& revision,
std::vector<Change> const& changes)
{
// Ignore changes in the old revision.
if(revision.Rev == this->OldRevision)
{
this->PriorRev = revision;
return;
}
// Indicate we found a revision.
cmCTestLog(this->CTest, HANDLER_OUTPUT, "." << std::flush);
// Store the revision.
this->Revisions.push_back(revision);
// Report this revision.
Revision const& rev = this->Revisions.back();
this->Log << "Found revision " << rev.Rev << "\n"
<< " author = " << rev.Author << "\n"
<< " date = " << rev.Date << "\n";
// Update information about revisions of the changed files.
for(std::vector<Change>::const_iterator ci = changes.begin();
ci != changes.end(); ++ci)
{
if(const char* local = this->LocalPath(ci->Path))
{
std::string dir = cmSystemTools::GetFilenamePath(local);
std::string name = cmSystemTools::GetFilenameName(local);
File& file = this->Dirs[dir][name];
file.PriorRev = file.Rev? file.Rev : &this->PriorRev;
file.Rev = &rev;
this->Log << " " << ci->Action << " " << local << " " << "\n";
}
}
}
//----------------------------------------------------------------------------
void cmCTestGlobalVC::DoModification(PathStatus status,
std::string const& path)
{
std::string dir = cmSystemTools::GetFilenamePath(path);
std::string name = cmSystemTools::GetFilenameName(path);
File& file = this->Dirs[dir][name];
file.Status = status;
// For local modifications the current rev is unknown and the
// prior rev is the latest from svn.
if(!file.Rev && !file.PriorRev)
{
file.PriorRev = &this->PriorRev;
}
}
//----------------------------------------------------------------------------
void cmCTestGlobalVC::WriteXMLDirectory(std::ostream& xml,
std::string const& path,
Directory const& dir)
{
const char* slash = path.empty()? "":"/";
xml << "\t<Directory>\n"
<< "\t\t<Name>" << cmXMLSafe(path) << "</Name>\n";
for(Directory::const_iterator fi = dir.begin(); fi != dir.end(); ++fi)
{
std::string full = path + slash + fi->first;
this->WriteXMLEntry(xml, path, fi->first, full, fi->second);
}
xml << "\t</Directory>\n";
}
//----------------------------------------------------------------------------
bool cmCTestGlobalVC::WriteXMLUpdates(std::ostream& xml)
{
cmCTestLog(this->CTest, HANDLER_OUTPUT,
" Gathering version information (one . per revision):\n"
" " << std::flush);
this->LoadRevisions();
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
this->LoadModifications();
for(std::map<cmStdString, Directory>::const_iterator
di = this->Dirs.begin(); di != this->Dirs.end(); ++di)
{
this->WriteXMLDirectory(xml, di->first, di->second);
}
return true;
}

View File

@ -0,0 +1,72 @@
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc. 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.
=========================================================================*/
#ifndef cmCTestGlobalVC_h
#define cmCTestGlobalVC_h
#include "cmCTestVC.h"
/** \class cmCTestGlobalVC
* \brief Base class for handling globally-versioned trees
*
*/
class cmCTestGlobalVC: public cmCTestVC
{
public:
/** Construct with a CTest instance and update log stream. */
cmCTestGlobalVC(cmCTest* ctest, std::ostream& log);
virtual ~cmCTestGlobalVC();
protected:
// Implement cmCTestVC internal API.
virtual bool WriteXMLUpdates(std::ostream& xml);
/** Represent a vcs-reported action for one path in a revision. */
struct Change
{
char Action;
std::string Path;
Change(char a = '?'): Action(a) {}
};
// Update status for files in each directory.
class Directory: public std::map<cmStdString, File> {};
std::map<cmStdString, Directory> Dirs;
// Old and new repository revisions.
std::string OldRevision;
std::string NewRevision;
// Information known about old revision.
Revision PriorRev;
// Information about revisions from a svn log.
std::list<Revision> Revisions;
virtual const char* LocalPath(std::string const& path);
virtual void DoRevision(Revision const& revision,
std::vector<Change> const& changes);
virtual void DoModification(PathStatus status, std::string const& path);
virtual void LoadModifications() = 0;
virtual void LoadRevisions() = 0;
void WriteXMLDirectory(std::ostream& xml, std::string const& path,
Directory const& dir);
};
#endif

View File

@ -24,7 +24,8 @@
#include <cmsys/RegularExpression.hxx>
//----------------------------------------------------------------------------
cmCTestSVN::cmCTestSVN(cmCTest* ct, std::ostream& log): cmCTestVC(ct, log)
cmCTestSVN::cmCTestSVN(cmCTest* ct, std::ostream& log):
cmCTestGlobalVC(ct, log)
{
this->PriorRev = this->Unknown;
}
@ -360,10 +361,6 @@ private:
//----------------------------------------------------------------------------
void cmCTestSVN::LoadRevisions()
{
cmCTestLog(this->CTest, HANDLER_OUTPUT,
" Gathering version information (one . per revision):\n"
" " << std::flush);
// We are interested in every revision included in the update.
std::string revs;
if(atoi(this->OldRevision.c_str()) < atoi(this->NewRevision.c_str()))
@ -383,7 +380,6 @@ void cmCTestSVN::LoadRevisions()
OutputLogger err(this->Log, "log-err> ");
this->RunChild(svn_log, &out, &err);
}
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
}
//----------------------------------------------------------------------------
@ -395,40 +391,7 @@ void cmCTestSVN::DoRevision(Revision const& revision,
{
this->GuessBase(changes);
}
// Indicate we found a revision.
cmCTestLog(this->CTest, HANDLER_OUTPUT, "." << std::flush);
// Ignore changes in the old revision.
if(revision.Rev == this->OldRevision)
{
this->PriorRev = revision;
return;
}
// Store the revision.
this->Revisions.push_back(revision);
// Report this revision.
Revision const& rev = this->Revisions.back();
this->Log << "Found revision " << rev.Rev << "\n"
<< " author = " << rev.Author << "\n"
<< " date = " << rev.Date << "\n";
// Update information about revisions of the changed files.
for(std::vector<Change>::const_iterator ci = changes.begin();
ci != changes.end(); ++ci)
{
if(const char* local = this->LocalPath(ci->Path))
{
std::string dir = cmSystemTools::GetFilenamePath(local);
std::string name = cmSystemTools::GetFilenameName(local);
File& file = this->Dirs[dir][name];
file.PriorRev = file.Rev? file.Rev : &this->PriorRev;
file.Rev = &rev;
this->Log << " " << ci->Action << " " << local << " " << "\n";
}
}
this->cmCTestGlobalVC::DoRevision(revision, changes);
}
//----------------------------------------------------------------------------
@ -461,29 +424,15 @@ private:
switch(status)
{
case 'M': case '!': case 'A': case 'D': case 'R': case 'X':
this->DoPath(PathModified, path);
this->SVN->DoModification(PathModified, path);
break;
case 'C': case '~':
this->DoPath(PathConflicting, path);
this->SVN->DoModification(PathConflicting, path);
break;
case 'I': case '?': case ' ': default:
break;
}
}
void DoPath(PathStatus status, std::string const& path)
{
std::string dir = cmSystemTools::GetFilenamePath(path);
std::string name = cmSystemTools::GetFilenameName(path);
File& file = this->SVN->Dirs[dir][name];
file.Status = status;
// For local modifications the current rev is unknown and the
// prior rev is the latest from svn.
if(!file.Rev && !file.PriorRev)
{
file.PriorRev = &this->SVN->PriorRev;
}
}
};
//----------------------------------------------------------------------------
@ -496,34 +445,3 @@ void cmCTestSVN::LoadModifications()
OutputLogger err(this->Log, "status-err> ");
this->RunChild(svn_status, &out, &err);
}
//----------------------------------------------------------------------------
void cmCTestSVN::WriteXMLDirectory(std::ostream& xml,
std::string const& path,
Directory const& dir)
{
const char* slash = path.empty()? "":"/";
xml << "\t<Directory>\n"
<< "\t\t<Name>" << cmXMLSafe(path) << "</Name>\n";
for(Directory::const_iterator fi = dir.begin(); fi != dir.end(); ++fi)
{
std::string full = path + slash + fi->first;
this->WriteXMLEntry(xml, path, fi->first, full, fi->second);
}
xml << "\t</Directory>\n";
}
//----------------------------------------------------------------------------
bool cmCTestSVN::WriteXMLUpdates(std::ostream& xml)
{
this->LoadRevisions();
this->LoadModifications();
for(std::map<cmStdString, Directory>::const_iterator
di = this->Dirs.begin(); di != this->Dirs.end(); ++di)
{
this->WriteXMLDirectory(xml, di->first, di->second);
}
return true;
}

View File

@ -17,13 +17,13 @@
#ifndef cmCTestSVN_h
#define cmCTestSVN_h
#include "cmCTestVC.h"
#include "cmCTestGlobalVC.h"
/** \class cmCTestSVN
* \brief Interaction with subversion command-line tool
*
*/
class cmCTestSVN: public cmCTestVC
class cmCTestSVN: public cmCTestGlobalVC
{
public:
/** Construct with a CTest instance and update log stream. */
@ -37,23 +37,6 @@ private:
virtual void NoteOldRevision();
virtual void NoteNewRevision();
virtual bool UpdateImpl();
virtual bool WriteXMLUpdates(std::ostream& xml);
/** Represent a subversion-reported action for one path in a revision. */
struct Change
{
char Action;
std::string Path;
Change(): Action('?') {}
};
// Update status for files in each directory.
class Directory: public std::map<cmStdString, File> {};
std::map<cmStdString, Directory> Dirs;
// Old and new repository revisions.
std::string OldRevision;
std::string NewRevision;
// URL of repository directory checked out in the working tree.
std::string URL;
@ -64,12 +47,6 @@ private:
// Directory under repository root checked out in working tree.
std::string Base;
// Information known about old revision.
Revision PriorRev;
// Information about revisions from a svn log.
std::list<Revision> Revisions;
std::string LoadInfo();
void LoadModifications();
void LoadRevisions();
@ -79,8 +56,6 @@ private:
void DoRevision(Revision const& revision,
std::vector<Change> const& changes);
void WriteXMLDirectory(std::ostream& xml, std::string const& path,
Directory const& dir);
// Parsing helper classes.
class InfoParser;