From d25289ad9254c67d8231c6582b4b9a35daa8297c Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Wed, 22 Apr 2009 09:18:19 -0400
Subject: 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.
---
 Source/CMakeLists.txt            |   2 +
 Source/CTest/cmCTestGlobalVC.cxx | 132 +++++++++++++++++++++++++++++++++++++++
 Source/CTest/cmCTestGlobalVC.h   |  72 +++++++++++++++++++++
 Source/CTest/cmCTestSVN.cxx      |  92 ++-------------------------
 Source/CTest/cmCTestSVN.h        |  29 +--------
 5 files changed, 213 insertions(+), 114 deletions(-)
 create mode 100644 Source/CTest/cmCTestGlobalVC.cxx
 create mode 100644 Source/CTest/cmCTestGlobalVC.h

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 1193363..bcc5999 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -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
diff --git a/Source/CTest/cmCTestGlobalVC.cxx b/Source/CTest/cmCTestGlobalVC.cxx
new file mode 100644
index 0000000..e628900
--- /dev/null
+++ b/Source/CTest/cmCTestGlobalVC.cxx
@@ -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;
+}
diff --git a/Source/CTest/cmCTestGlobalVC.h b/Source/CTest/cmCTestGlobalVC.h
new file mode 100644
index 0000000..fbb794e
--- /dev/null
+++ b/Source/CTest/cmCTestGlobalVC.h
@@ -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
diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx
index ef3a4a7..cddcacf 100644
--- a/Source/CTest/cmCTestSVN.cxx
+++ b/Source/CTest/cmCTestSVN.cxx
@@ -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;
-}
diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h
index 32b472d..5af0bac 100644
--- a/Source/CTest/cmCTestSVN.h
+++ b/Source/CTest/cmCTestSVN.h
@@ -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;
-- 
cgit v0.12