From 8ddf922005fb0fea39964fb7d6ad6fae9f27cbd2 Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 25 May 2016 20:36:04 +0100 Subject: [PATCH] Remove SVN sync code. --- simgear/io/CMakeLists.txt | 11 - simgear/io/DAVMultiStatus.cxx | 402 ---------------------- simgear/io/DAVMultiStatus.hxx | 143 -------- simgear/io/SVNDirectory.cxx | 400 ---------------------- simgear/io/SVNDirectory.hxx | 109 ------ simgear/io/SVNReportParser.cxx | 605 --------------------------------- simgear/io/SVNReportParser.hxx | 57 ---- simgear/io/SVNRepository.cxx | 386 --------------------- simgear/io/SVNRepository.hxx | 59 ---- simgear/io/http_svn.cxx | 51 --- 10 files changed, 2223 deletions(-) delete mode 100644 simgear/io/DAVMultiStatus.cxx delete mode 100644 simgear/io/DAVMultiStatus.hxx delete mode 100644 simgear/io/SVNDirectory.cxx delete mode 100644 simgear/io/SVNDirectory.hxx delete mode 100644 simgear/io/SVNReportParser.cxx delete mode 100644 simgear/io/SVNReportParser.hxx delete mode 100644 simgear/io/SVNRepository.cxx delete mode 100644 simgear/io/SVNRepository.hxx delete mode 100644 simgear/io/http_svn.cxx diff --git a/simgear/io/CMakeLists.txt b/simgear/io/CMakeLists.txt index 00d072d5..71213551 100644 --- a/simgear/io/CMakeLists.txt +++ b/simgear/io/CMakeLists.txt @@ -19,10 +19,6 @@ set(HEADERS HTTPMemoryRequest.hxx HTTPRequest.hxx AbstractRepository.hxx - DAVMultiStatus.hxx - SVNRepository.hxx - SVNDirectory.hxx - SVNReportParser.hxx HTTPRepository.hxx ) @@ -43,10 +39,6 @@ set(SOURCES HTTPMemoryRequest.cxx HTTPRequest.cxx AbstractRepository.cxx - DAVMultiStatus.cxx - SVNRepository.cxx - SVNDirectory.cxx - SVNReportParser.cxx HTTPRepository.cxx ) @@ -59,9 +51,6 @@ simgear_component(io io "${SOURCES}" "${HEADERS}") if(ENABLE_TESTS) -add_executable(http_svn http_svn.cxx) -target_link_libraries(http_svn ${TEST_LIBS}) - add_executable(test_sock socktest.cxx) target_link_libraries(test_sock ${TEST_LIBS}) diff --git a/simgear/io/DAVMultiStatus.cxx b/simgear/io/DAVMultiStatus.cxx deleted file mode 100644 index 6a82a0c5..00000000 --- a/simgear/io/DAVMultiStatus.cxx +++ /dev/null @@ -1,402 +0,0 @@ -// DAVMultiStatus.cxx -- parser for WebDAV MultiStatus XML data -// -// Copyright (C) 2012 James Turner -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "DAVMultiStatus.hxx" - -#include -#include -#include -#include -#include - -#include - -#include "simgear/debug/logstream.hxx" -#include "simgear/misc/strutils.hxx" -#include "simgear/structure/exception.hxx" - -#ifdef SYSTEM_EXPAT -# include -#else -# include "sg_expat.h" -#endif - -using std::string; - -using namespace simgear; - -#define DAV_NS "DAV::" -#define SUBVERSION_DAV_NS "http://subversion.tigris.org/xmlns/dav/" - -const char* DAV_MULTISTATUS_TAG = DAV_NS "multistatus"; -const char* DAV_RESPONSE_TAG = DAV_NS "response"; -const char* DAV_PROPSTAT_TAG = DAV_NS "propstat"; -const char* DAV_PROP_TAG = DAV_NS "prop"; - -const char* DAV_HREF_TAG = DAV_NS "href"; -const char* DAV_RESOURCE_TYPE_TAG = DAV_NS "resourcetype"; -const char* DAV_CONTENT_TYPE_TAG = DAV_NS "getcontenttype"; -const char* DAV_CONTENT_LENGTH_TAG = DAV_NS "getcontentlength"; -const char* DAV_VERSIONNAME_TAG = DAV_NS "version-name"; -const char* DAV_COLLECTION_TAG = DAV_NS "collection"; -const char* DAV_VCC_TAG = DAV_NS "version-controlled-configuration"; - -const char* SUBVERSION_MD5_CHECKSUM_TAG = SUBVERSION_DAV_NS ":md5-checksum"; - -DAVResource::DAVResource(const string& href) : - _type(Unknown), - _url(href), - _container(NULL) -{ - assert(!href.empty()); - if (strutils::ends_with(href, "/")) { - _url = href.substr(0, _url.size() - 1); - } -} - -void DAVResource::setVersionName(const std::string& aVersion) -{ - _versionName = aVersion; -} - -void DAVResource::setVersionControlledConfiguration(const std::string& vcc) -{ - _vcc = vcc; -} - -void DAVResource::setMD5(const std::string& md5Hex) -{ - _md5 = md5Hex; -} - -std::string DAVResource::name() const -{ - string::size_type index = _url.rfind('/'); - if (index != string::npos) { - return _url.substr(index + 1); - } - - throw sg_exception("bad DAV resource HREF:" + _url); -} - -//////////////////////////////////////////////////////////////////////////// - -DAVCollection::DAVCollection(const string& href) : - DAVResource(href) -{ - _type = DAVResource::Collection; -} - -DAVCollection::~DAVCollection() -{ - BOOST_FOREACH(DAVResource* c, _contents) { - delete c; - } -} - -void DAVCollection::addChild(DAVResource *res) -{ - assert(res); - if (res->container() == this) { - return; - } - - assert(res->container() == NULL); - assert(std::find(_contents.begin(), _contents.end(), res) == _contents.end()); - assert(strutils::starts_with(res->url(), _url)); - assert(childWithUrl(res->url()) == NULL); - - res->_container = this; - _contents.push_back(res); -} - -void DAVCollection::removeChild(DAVResource* res) -{ - assert(res); - assert(res->container() == this); - - res->_container = NULL; - DAVResourceList::iterator it = std::find(_contents.begin(), _contents.end(), res); - assert(it != _contents.end()); - _contents.erase(it); -} - -DAVCollection* -DAVCollection::createChildCollection(const std::string& name) -{ - DAVCollection* child = new DAVCollection(urlForChildWithName(name)); - addChild(child); - return child; -} - -DAVResourceList DAVCollection::contents() const -{ - return _contents; -} - -DAVResource* DAVCollection::childWithUrl(const string& url) const -{ - if (url.empty()) - return NULL; - - BOOST_FOREACH(DAVResource* c, _contents) { - if (c->url() == url) { - return c; - } - } - - return NULL; -} - -DAVResource* DAVCollection::childWithName(const string& name) const -{ - return childWithUrl(urlForChildWithName(name)); -} - -std::string DAVCollection::urlForChildWithName(const std::string& name) const -{ - return url() + "/" + name; -} - -/////////////////////////////////////////////////////////////////////////////// - -class DAVMultiStatus::DAVMultiStatusPrivate -{ -public: - DAVMultiStatusPrivate() : - parserInited(false), - valid(false) - { - rootResource = NULL; - } - - void startElement (const char * name) - { - if (tagStack.empty()) { - if (strcmp(name, DAV_MULTISTATUS_TAG)) { - SG_LOG(SG_TERRASYNC, SG_WARN, "root element is not " << - DAV_MULTISTATUS_TAG << ", got:" << name); - } else { - - } - } else { - // not at the root element - if (tagStack.back() == DAV_MULTISTATUS_TAG) { - if (strcmp(name, DAV_RESPONSE_TAG)) { - SG_LOG(SG_TERRASYNC, SG_WARN, "multistatus child is not response: saw:" - << name); - } - } - - if (tagStack.back() == DAV_RESOURCE_TYPE_TAG) { - if (!strcmp(name, DAV_COLLECTION_TAG)) { - currentElementType = DAVResource::Collection; - } else { - currentElementType = DAVResource::Unknown; - } - } - } - - tagStack.push_back(name); - if (!strcmp(name, DAV_RESPONSE_TAG)) { - currentElementType = DAVResource::Unknown; - currentElementUrl.clear(); - currentElementMD5.clear(); - currentVersionName.clear(); - currentVCC.clear(); - } - } - - void endElement (const char * name) - { - assert(tagStack.back() == name); - tagStack.pop_back(); - - if (!strcmp(name, DAV_RESPONSE_TAG)) { - // finish complete response - currentElementUrl = strutils::strip(currentElementUrl); - - DAVResource* res = NULL; - if (currentElementType == DAVResource::Collection) { - DAVCollection* col = new DAVCollection(currentElementUrl); - res = col; - } else { - res = new DAVResource(currentElementUrl); - } - - res->setVersionName(strutils::strip(currentVersionName)); - res->setVersionControlledConfiguration(currentVCC); - if (rootResource && - strutils::starts_with(currentElementUrl, rootResource->url())) - { - static_cast(rootResource)->addChild(res); - } - - if (!rootResource) { - rootResource = res; - } - } - } - - void data (const char * s, int length) - { - if (tagStack.back() == DAV_HREF_TAG) { - if (tagN(1) == DAV_RESPONSE_TAG) { - currentElementUrl += string(s, length); - } else if (tagN(1) == DAV_VCC_TAG) { - currentVCC += string(s, length); - } - } else if (tagStack.back() == SUBVERSION_MD5_CHECKSUM_TAG) { - currentElementMD5 = string(s, length); - } else if (tagStack.back() == DAV_VERSIONNAME_TAG) { - currentVersionName = string(s, length); - } else if (tagStack.back() == DAV_CONTENT_LENGTH_TAG) { - std::istringstream is(string(s, length)); - is >> currentElementLength; - } - } - - void pi (const char * target, const char * data) {} - - string tagN(const unsigned int n) const - { - size_t sz = tagStack.size(); - if (n >= sz) { - return string(); - } - - return tagStack[sz - (1 + n)]; - } - - bool parserInited; - bool valid; - XML_Parser xmlParser; - DAVResource* rootResource; - - // in-flight data - string_list tagStack; - DAVResource::Type currentElementType; - string currentElementUrl, - currentVersionName, - currentVCC; - int currentElementLength; - string currentElementMD5; -}; - - -//////////////////////////////////////////////////////////////////////// -// Static callback functions for Expat. -//////////////////////////////////////////////////////////////////////// - -#define VISITOR static_cast(userData) - -static void -start_element (void * userData, const char * name, const char ** atts) -{ - VISITOR->startElement(name); -} - -static void -end_element (void * userData, const char * name) -{ - VISITOR->endElement(name); -} - -static void -character_data (void * userData, const char * s, int len) -{ - VISITOR->data(s, len); -} - -static void -processing_instruction (void * userData, - const char * target, - const char * data) -{ - VISITOR->pi(target, data); -} - -#undef VISITOR - -/////////////////////////////////////////////////////////////////////////////// - -DAVMultiStatus::DAVMultiStatus() : -_d(new DAVMultiStatusPrivate) -{ - -} - -DAVMultiStatus::~DAVMultiStatus() -{ - -} - -void DAVMultiStatus::parseXML(const char* data, int size) -{ - if (!_d->parserInited) { - _d->xmlParser = XML_ParserCreateNS(0, ':'); - XML_SetUserData(_d->xmlParser, _d.get()); - XML_SetElementHandler(_d->xmlParser, start_element, end_element); - XML_SetCharacterDataHandler(_d->xmlParser, character_data); - XML_SetProcessingInstructionHandler(_d->xmlParser, processing_instruction); - _d->parserInited = true; - } - - if (!XML_Parse(_d->xmlParser, data, size, false)) { - SG_LOG(SG_TERRASYNC, SG_WARN, "DAV parse error:" << XML_ErrorString(XML_GetErrorCode(_d->xmlParser)) - << " at line:" << XML_GetCurrentLineNumber(_d->xmlParser) - << " column " << XML_GetCurrentColumnNumber(_d->xmlParser)); - - XML_ParserFree(_d->xmlParser); - _d->parserInited = false; - _d->valid = false; - } -} - -void DAVMultiStatus::finishParse() -{ - if (_d->parserInited) { - if (!XML_Parse(_d->xmlParser, NULL, 0, true)) { - SG_LOG(SG_TERRASYNC, SG_WARN, "DAV parse error:" << XML_ErrorString(XML_GetErrorCode(_d->xmlParser)) - << " at line:" << XML_GetCurrentLineNumber(_d->xmlParser) - << " column " << XML_GetCurrentColumnNumber(_d->xmlParser)); - _d->valid = false; - } else { - _d->valid = true; - } - XML_ParserFree(_d->xmlParser); - } - - _d->parserInited = false; -} - -DAVResource* DAVMultiStatus::resource() -{ - return _d->rootResource; -} - -bool DAVMultiStatus::isValid() const -{ - return _d->valid; -} - - diff --git a/simgear/io/DAVMultiStatus.hxx b/simgear/io/DAVMultiStatus.hxx deleted file mode 100644 index d415e5ae..00000000 --- a/simgear/io/DAVMultiStatus.hxx +++ /dev/null @@ -1,143 +0,0 @@ -// DAVMultiStatus.hxx -- parser for WebDAV MultiStatus XML data -// -// Copyright (C) 2012 James Turner -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - -#ifndef SG_IO_DAVMULTISTATUS_HXX -#define SG_IO_DAVMULTISTATUS_HXX - -#include -#include -#include // for auto_ptr - -namespace simgear -{ - -class DAVCollection; - -class DAVResource -{ -public: - DAVResource(const std::string& url); - virtual ~DAVResource() { } - - typedef enum { - Unknown = 0, - Collection = 1 - } Type; - - const Type type() const - { return _type; } - - const std::string& url() const - { return _url; } - - std::string name() const; - - /** - * SVN servers use this field to expose the head revision - * of the resource, which is useful - */ - const std::string& versionName() const - { return _versionName; } - - void setVersionName(const std::string& aVersion); - - DAVCollection* container() const - { return _container; } - - virtual bool isCollection() const - { return false; } - - void setVersionControlledConfiguration(const std::string& vcc); - const std::string& versionControlledConfiguration() const - { return _vcc; } - - void setMD5(const std::string& md5Hex); - const std::string& md5() const - { return _md5; } -protected: - friend class DAVCollection; - - Type _type; - std::string _url; - std::string _versionName; - std::string _vcc; - std::string _md5; - DAVCollection* _container; -}; - -typedef std::vector DAVResourceList; - -class DAVCollection : public DAVResource -{ -public: - DAVCollection(const std::string& url); - virtual ~DAVCollection(); - - DAVResourceList contents() const; - - void addChild(DAVResource* res); - void removeChild(DAVResource* res); - - DAVCollection* createChildCollection(const std::string& name); - - /** - * find the collection member with the specified URL, or return NULL - * if no such member of this collection exists. - */ - DAVResource* childWithUrl(const std::string& url) const; - - /** - * find the collection member with the specified name, or return NULL - */ - DAVResource* childWithName(const std::string& name) const; - - /** - * wrapper around URL manipulation - */ - std::string urlForChildWithName(const std::string& name) const; - - virtual bool isCollection() const - { return true; } -private: - DAVResourceList _contents; -}; - -class DAVMultiStatus -{ -public: - DAVMultiStatus(); - ~DAVMultiStatus(); - - // incremental XML parsing - void parseXML(const char* data, int size); - - void finishParse(); - - bool isValid() const; - - DAVResource* resource(); - - class DAVMultiStatusPrivate; -private: - std::auto_ptr _d; -}; - -} // of namespace simgear - -#endif // of SG_IO_DAVMULTISTATUS_HXX diff --git a/simgear/io/SVNDirectory.cxx b/simgear/io/SVNDirectory.cxx deleted file mode 100644 index 267d3120..00000000 --- a/simgear/io/SVNDirectory.cxx +++ /dev/null @@ -1,400 +0,0 @@ - -#include "SVNDirectory.hxx" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using std::string; -using std::cout; -using std::endl; -using namespace simgear; - -typedef std::vector RequestVector; -typedef std::map DAVResourceMap; - - -const char* DAV_CACHE_NAME = ".terrasync_cache"; -const char* CACHE_VERSION_4_TOKEN = "terrasync-cache-4"; - -// important: with the Google servers, setting this higher than '1' causes -// server internal errors (500, the connection is closed). In other words we -// can only specify update report items one level deep at most and no more. -// (the root and its direct children, not NOT grand-children) -const unsigned int MAX_UPDATE_REPORT_DEPTH = 1; - -enum LineState -{ - LINESTATE_HREF = 0, - LINESTATE_VERSIONNAME -}; - -SVNDirectory::SVNDirectory(SVNRepository *r, const SGPath& path) : - localPath(path), - dav(NULL), - repo(r), - _doingUpdateReport(false), - _parent(NULL) -{ - if (path.exists()) { - parseCache(); - } - - // don't create dir here, repo might not exist at all -} - -SVNDirectory::SVNDirectory(SVNDirectory* pr, DAVCollection* col) : - dav(col), - repo(pr->repository()), - _doingUpdateReport(false), - _parent(pr) -{ - assert(col->container()); - assert(!col->url().empty()); - assert(_parent); - - localPath = pr->fsDir().file(col->name()); - if (!localPath.exists()) { - Dir d(localPath); - d.create(0755); - writeCache(); - } else { - parseCache(); - } -} - -SVNDirectory::~SVNDirectory() -{ - // recursive delete our child directories - BOOST_FOREACH(SVNDirectory* d, _children) { - delete d; - } -} - -void SVNDirectory::parseCache() -{ - SGPath p(localPath); - p.append(DAV_CACHE_NAME); - if (!p.exists()) { - return; - } - - char href[1024]; - char versionName[128]; - LineState lineState = LINESTATE_HREF; - std::ifstream file(p.c_str()); - if (!file.is_open()) { - SG_LOG(SG_TERRASYNC, SG_WARN, "unable to open cache file for reading:" << p); - return; - } - bool doneSelf = false; - - file.getline(href, 1024); - if (strcmp(CACHE_VERSION_4_TOKEN, href)) { - SG_LOG(SG_TERRASYNC, SG_WARN, "invalid cache file [missing header token]:" << p << " '" << href << "'"); - return; - } - - std::string vccUrl; - file.getline(href, 1024); - vccUrl = href; - - while (!file.eof()) { - if (lineState == LINESTATE_HREF) { - file.getline(href, 1024); - lineState = LINESTATE_VERSIONNAME; - } else { - assert(lineState == LINESTATE_VERSIONNAME); - file.getline(versionName, 1024); - lineState = LINESTATE_HREF; - char* hrefPtr = href; - - if (!doneSelf) { - if (!dav) { - dav = new DAVCollection(hrefPtr); - dav->setVersionName(versionName); - } else { - assert(string(hrefPtr) == dav->url()); - } - - if (!vccUrl.empty()) { - dav->setVersionControlledConfiguration(vccUrl); - } - - _cachedRevision = versionName; - doneSelf = true; - } else { - DAVResource* child = parseChildDirectory(hrefPtr)->collection(); - string s = strutils::strip(versionName); - if (!s.empty()) { - child->setVersionName(versionName); - } - } // of done self test - } // of line-state switching - } // of file get-line loop -} - -void SVNDirectory::writeCache() -{ - SGPath p(localPath); - if (!p.exists()) { - Dir d(localPath); - d.create(0755); - } - - p.append(string(DAV_CACHE_NAME) + ".new"); - - std::ofstream file(p.c_str(), std::ios::trunc); -// first, cache file version header - file << CACHE_VERSION_4_TOKEN << '\n'; - -// second, the repository VCC url - file << dav->versionControlledConfiguration() << '\n'; - -// third, our own URL, and version - file << dav->url() << '\n' << _cachedRevision << '\n'; - - BOOST_FOREACH(DAVResource* child, dav->contents()) { - if (child->isCollection()) { - file << child->name() << '\n' << child->versionName() << "\n"; - } - } // of child iteration - - file.close(); - -// approximately atomic delete + rename operation - SGPath cacheName(localPath); - cacheName.append(DAV_CACHE_NAME); - p.rename(cacheName); -} - -void SVNDirectory::setBaseUrl(const string& url) -{ - if (_parent) { - SG_LOG(SG_TERRASYNC, SG_ALERT, "setting base URL on non-root directory " << url); - return; - } - - if (dav && (url == dav->url())) { - return; - } - - dav = new DAVCollection(url); -} - -std::string SVNDirectory::url() const -{ - if (!_parent) { - return repo->baseUrl(); - } - - return _parent->url() + "/" + name(); -} - -std::string SVNDirectory::name() const -{ - return dav->name(); -} - -DAVResource* -SVNDirectory::addChildFile(const std::string& fileName) -{ - DAVResource* child = NULL; - child = new DAVResource(dav->urlForChildWithName(fileName)); - dav->addChild(child); - - writeCache(); - return child; -} - -SVNDirectory* -SVNDirectory::addChildDirectory(const std::string& dirName) -{ - if (dav->childWithName(dirName)) { - // existing child, let's remove it - deleteChildByName(dirName); - } - - DAVCollection* childCol = dav->createChildCollection(dirName); - SVNDirectory* child = new SVNDirectory(this, childCol); - childCol->setVersionName(child->cachedRevision()); - _children.push_back(child); - writeCache(); - return child; -} - -SVNDirectory* -SVNDirectory::parseChildDirectory(const std::string& dirName) -{ - assert(!dav->childWithName(dirName)); - DAVCollection* childCol = dav->createChildCollection(dirName); - SVNDirectory* child = new SVNDirectory(this, childCol); - childCol->setVersionName(child->cachedRevision()); - _children.push_back(child); - return child; -} - -void SVNDirectory::deleteChildByName(const std::string& nm) -{ - DAVResource* child = dav->childWithName(nm); - if (!child) { - return; - } - - SGPath path = fsDir().file(nm); - - if (child->isCollection()) { - Dir d(path); - bool ok = d.remove(true); - if (!ok) { - SG_LOG(SG_TERRASYNC, SG_ALERT, "SVNDirectory::deleteChildByName: failed to remove dir:" - << nm << " at path:\n\t" << path); - } - - DirectoryList::iterator it = findChildDir(nm); - if (it != _children.end()) { - SVNDirectory* c = *it; - delete c; - _children.erase(it); - } - } else { - bool ok = path.remove(); - if (!ok) { - SG_LOG(SG_TERRASYNC, SG_ALERT, "SVNDirectory::deleteChildByName: failed to remove path:" << nm - << " at path:\n\t" << path); - } - } - - dav->removeChild(child); - delete child; - - writeCache(); -} - -bool SVNDirectory::isDoingSync() const -{ - if (_doingUpdateReport) { - return true; - } - - BOOST_FOREACH(SVNDirectory* child, _children) { - if (child->isDoingSync()) { - return true; - } // of children - } - - return false; -} - -void SVNDirectory::beginUpdateReport() -{ - _doingUpdateReport = true; - _cachedRevision.clear(); - writeCache(); -} - -void SVNDirectory::updateReportComplete() -{ - _cachedRevision = dav->versionName(); - _doingUpdateReport = false; - writeCache(); - - SVNDirectory* pr = parent(); - if (pr) { - pr->writeCache(); - } -} - -SVNRepository* SVNDirectory::repository() const -{ - return repo; -} - -void SVNDirectory::mergeUpdateReportDetails(unsigned int depth, - string_list& items) -{ - // normal, easy case: we are fully in-sync at a revision - if (!_cachedRevision.empty()) { - std::ostringstream os; - os << "" - << repoPath() << ""; - items.push_back(os.str()); - return; - } - - Dir d(localPath); - if (depth >= MAX_UPDATE_REPORT_DEPTH) { - d.removeChildren(); - return; - } - - PathList cs = d.children(Dir::NO_DOT_OR_DOTDOT | Dir::INCLUDE_HIDDEN | Dir::TYPE_DIR); - BOOST_FOREACH(SGPath path, cs) { - SVNDirectory* c = child(path.file()); - if (!c) { - // ignore this child, if it's an incomplete download, - // it will be over-written on the update anyway - //std::cerr << "unknown SVN child" << path << std::endl; - } else { - // recurse down into children - c->mergeUpdateReportDetails(depth+1, items); - } - } // of child dir iteration -} - -std::string SVNDirectory::repoPath() const -{ - if (!_parent) { - return "/"; - } - - // find the length of the repository base URL, then - // trim that off our repo URL - job done! - size_t baseUrlLen = repo->baseUrl().size(); - return dav->url().substr(baseUrlLen + 1); -} - -SVNDirectory* SVNDirectory::parent() const -{ - return _parent; -} - -SVNDirectory* SVNDirectory::child(const std::string& dirName) const -{ - BOOST_FOREACH(SVNDirectory* d, _children) { - if (d->name() == dirName) { - return d; - } - } - - return NULL; -} - -DirectoryList::iterator -SVNDirectory::findChildDir(const std::string& dirName) -{ - DirectoryList::iterator it; - for (it=_children.begin(); it != _children.end(); ++it) { - if ((*it)->name() == dirName) { - return it; - } - } - return it; -} - -simgear::Dir SVNDirectory::fsDir() const -{ - return Dir(localPath); -} diff --git a/simgear/io/SVNDirectory.hxx b/simgear/io/SVNDirectory.hxx deleted file mode 100644 index 1d7122cc..00000000 --- a/simgear/io/SVNDirectory.hxx +++ /dev/null @@ -1,109 +0,0 @@ -// DAVCollectionMirror.hxx - mirror a DAV collection to the local filesystem -// -// Copyright (C) 2013 James Turner -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - -#ifndef SG_IO_DAVCOLLECTIONMIRROR_HXX -#define SG_IO_DAVCOLLECTIONMIRROR_HXX - -#include -#include -#include - -#include -#include -#include - -namespace simgear { - -class Dir; -namespace HTTP { class Request; } - -// forward decls -class DAVMirror; -class SVNRepository; -class SVNDirectory; - -typedef std::vector DirectoryList; - -class SVNDirectory -{ -public: - // init from local - SVNDirectory(SVNRepository *repo, const SGPath& path); - ~SVNDirectory(); - - void setBaseUrl(const std::string& url); - - // init from a collection - SVNDirectory(SVNDirectory* pr, DAVCollection* col); - - void beginUpdateReport(); - void updateReportComplete(); - - bool isDoingSync() const; - - std::string url() const; - - std::string name() const; - - DAVResource* addChildFile(const std::string& fileName); - SVNDirectory* addChildDirectory(const std::string& dirName); - - // void updateChild(DAVResource* child); - void deleteChildByName(const std::string& name); - - SGPath fsPath() const - { return localPath; } - - simgear::Dir fsDir() const; - - std::string repoPath() const; - - SVNRepository* repository() const; - DAVCollection* collection() const - { return dav; } - - std::string cachedRevision() const - { return _cachedRevision; } - - void mergeUpdateReportDetails(unsigned int depth, string_list& items); - - SVNDirectory* parent() const; - SVNDirectory* child(const std::string& dirName) const; -private: - - void parseCache(); - void writeCache(); - - DirectoryList::iterator findChildDir(const std::string& dirName); - SVNDirectory* parseChildDirectory(const std::string& dirName); - - SGPath localPath; - DAVCollection* dav; - SVNRepository* repo; - - std::string _cachedRevision; - bool _doingUpdateReport; - - SVNDirectory* _parent; - DirectoryList _children; -}; - -} // of namespace simgear - -#endif // of SG_IO_DAVCOLLECTIONMIRROR_HXX diff --git a/simgear/io/SVNReportParser.cxx b/simgear/io/SVNReportParser.cxx deleted file mode 100644 index 5ee3d63f..00000000 --- a/simgear/io/SVNReportParser.cxx +++ /dev/null @@ -1,605 +0,0 @@ -// SVNReportParser -- parser for SVN report XML data -// -// Copyright (C) 2012 James Turner -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "SVNReportParser.hxx" - -#include -#include -#include -#include -#include -#include - -#include - -#include "simgear/misc/sg_path.hxx" -#include "simgear/misc/sg_dir.hxx" -#include "simgear/debug/logstream.hxx" -#include "simgear/xml/easyxml.hxx" -#include "simgear/misc/strutils.hxx" -#include "simgear/package/md5.h" - -#ifdef SYSTEM_EXPAT -# include -#else -# include "sg_expat.h" -#endif - -#include "SVNDirectory.hxx" -#include "SVNRepository.hxx" -#include "DAVMultiStatus.hxx" - -using std::cout; -using std::cerr; -using std::endl; -using std::string; - -using namespace simgear; - -#define DAV_NS "DAV::" -#define SVN_NS "svn::" -#define SUBVERSION_DAV_NS "http://subversion.tigris.org/xmlns/dav/" - -namespace { - - #define MAX_ENCODED_INT_LEN 10 - - static size_t - decode_size(unsigned char* &p, - const unsigned char *end) - { - if (p + MAX_ENCODED_INT_LEN < end) - end = p + MAX_ENCODED_INT_LEN; - /* Decode bytes until we're done. */ - size_t result = 0; - - while (p < end) { - result = (result << 7) | (*p & 0x7f); - if (((*p++ >> 7) & 0x1) == 0) { - break; - } - } - - return result; - } - - static bool - try_decode_size(unsigned char* &p, - const unsigned char *end) - { - if (p + MAX_ENCODED_INT_LEN < end) - end = p + MAX_ENCODED_INT_LEN; - - while (p < end) { - if (((*p++ >> 7) & 0x1) == 0) { - return true; - } - } - - return false; - } - -// const char* SVN_UPDATE_REPORT_TAG = SVN_NS "update-report"; - // const char* SVN_TARGET_REVISION_TAG = SVN_NS "target-revision"; - const char* SVN_OPEN_DIRECTORY_TAG = SVN_NS "open-directory"; - const char* SVN_OPEN_FILE_TAG = SVN_NS "open-file"; - const char* SVN_ADD_DIRECTORY_TAG = SVN_NS "add-directory"; - const char* SVN_ADD_FILE_TAG = SVN_NS "add-file"; - const char* SVN_TXDELTA_TAG = SVN_NS "txdelta"; - const char* SVN_SET_PROP_TAG = SVN_NS "set-prop"; - const char* SVN_PROP_TAG = SVN_NS "prop"; - const char* SVN_DELETE_ENTRY_TAG = SVN_NS "delete-entry"; - - const char* SVN_DAV_MD5_CHECKSUM = SUBVERSION_DAV_NS ":md5-checksum"; - - const char* DAV_HREF_TAG = DAV_NS "href"; - const char* DAV_CHECKED_IN_TAG = DAV_NS "checked-in"; - - - const int svn_txdelta_source = 0; - const int svn_txdelta_target = 1; - const int svn_txdelta_new = 2; - - const size_t DELTA_HEADER_SIZE = 4; - - /** - * helper struct to decode and store the SVN delta header - * values - */ - struct SVNDeltaWindow - { - public: - - static bool isWindowComplete(unsigned char* buffer, size_t bytes) - { - unsigned char* p = buffer; - unsigned char* pEnd = p + bytes; - // if we can't decode five sizes, certainly incomplete - for (int i=0; i<5; i++) { - if (!try_decode_size(p, pEnd)) { - return false; - } - } - - p = buffer; - // ignore these three - decode_size(p, pEnd); - decode_size(p, pEnd); - decode_size(p, pEnd); - size_t instructionLen = decode_size(p, pEnd); - size_t newLength = decode_size(p, pEnd); - size_t headerLength = p - buffer; - - return (bytes >= (instructionLen + newLength + headerLength)); - } - - SVNDeltaWindow(unsigned char* p) : - headerLength(0), - _ptr(p) - { - sourceViewOffset = decode_size(p, p+20); - sourceViewLength = decode_size(p, p+20); - targetViewLength = decode_size(p, p+20); - instructionLength = decode_size(p, p+20); - newLength = decode_size(p, p+20); - - headerLength = p - _ptr; - _ptr = p; - } - - bool apply(std::vector& output, std::istream& source) - { - unsigned char* pEnd = _ptr + instructionLength; - unsigned char* newData = pEnd; - - while (_ptr < pEnd) { - int op = ((*_ptr >> 6) & 0x3); - if (op >= 3) { - SG_LOG(SG_IO, SG_INFO, "SVNDeltaWindow: bad opcode:" << op); - return false; - } - - int length = *_ptr++ & 0x3f; - int offset = 0; - - if (length == 0) { - length = decode_size(_ptr, pEnd); - } - - if (length == 0) { - SG_LOG(SG_IO, SG_INFO, "SVNDeltaWindow: malformed stream, 0 length" << op); - return false; - } - - // if op != new, decode another size value - if (op != svn_txdelta_new) { - offset = decode_size(_ptr, pEnd); - } - - if (op == svn_txdelta_target) { - // this is inefficent, but ranges can overlap. - while (length > 0) { - output.push_back(output[offset++]); - --length; - } - } else if (op == svn_txdelta_new) { - output.insert(output.end(), newData, newData + length); - newData += length; - } else if (op == svn_txdelta_source) { - source.seekg(offset); - char* sourceBuf = (char*) malloc(length); - assert(sourceBuf); - source.read(sourceBuf, length); - output.insert(output.end(), sourceBuf, sourceBuf + length); - free(sourceBuf); - } else { - SG_LOG(SG_IO, SG_WARN, "bad opcode logic"); - return false; - } - } // of instruction loop - - return true; - } - - size_t size() const - { - return headerLength + instructionLength + newLength; - } - - unsigned int sourceViewOffset; - size_t sourceViewLength, - targetViewLength; - size_t headerLength, - instructionLength, - newLength; - -private: - unsigned char* _ptr; - }; - - -} // of anonymous namespace - -class SVNReportParser::SVNReportParserPrivate -{ -public: - SVNReportParserPrivate(SVNRepository* repo) : - tree(repo), - status(AbstractRepository::REPO_NO_ERROR), - parserInited(false), - currentPath(repo->fsBase()) - { - inFile = false; - currentDir = repo->rootDir(); - } - - ~SVNReportParserPrivate() - { - } - - void startElement (const char * name, const char** attributes) - { - if (status != AbstractRepository::REPO_NO_ERROR) { - return; - } - - ExpatAtts attrs(attributes); - tagStack.push_back(name); - if (!strcmp(name, SVN_TXDELTA_TAG)) { - txDeltaData.clear(); - } else if (!strcmp(name, SVN_ADD_FILE_TAG)) { - string fileName(attrs.getValue("name")); - SGPath filePath(currentDir->fsDir().file(fileName)); - currentPath = filePath; - inFile = true; - } else if (!strcmp(name, SVN_OPEN_FILE_TAG)) { - string fileName(attrs.getValue("name")); - SGPath filePath(Dir(currentPath).file(fileName)); - currentPath = filePath; - - if (!filePath.exists()) { - fail(AbstractRepository::REPO_ERROR_FILE_NOT_FOUND); - return; - } - - inFile = true; - } else if (!strcmp(name, SVN_ADD_DIRECTORY_TAG)) { - string dirName(attrs.getValue("name")); - Dir d(currentDir->fsDir().file(dirName)); - if (d.exists()) { - // policy decision : if we're doing an add, wipe the existing - d.remove(true); - } - - currentDir = currentDir->addChildDirectory(dirName); - currentPath = currentDir->fsPath(); - currentDir->beginUpdateReport(); - //cout << "addDir:" << currentPath << endl; - } else if (!strcmp(name, SVN_SET_PROP_TAG)) { - setPropName = attrs.getValue("name"); - setPropValue.clear(); - } else if (!strcmp(name, SVN_DAV_MD5_CHECKSUM)) { - md5Sum.clear(); - } else if (!strcmp(name, SVN_OPEN_DIRECTORY_TAG)) { - string dirName; - if (attrs.getValue("name")) { - dirName = string(attrs.getValue("name")); - } - openDirectory(dirName); - } else if (!strcmp(name, SVN_DELETE_ENTRY_TAG)) { - string entryName(attrs.getValue("name")); - deleteEntry(entryName); - } else if (!strcmp(name, DAV_CHECKED_IN_TAG) || - !strcmp(name, DAV_HREF_TAG) || - !strcmp(name, SVN_PROP_TAG)) { - // don't warn on these ones - } else { - //SG_LOG(SG_IO, SG_WARN, "SVNReportParser: unhandled tag:" << name); - } - } // of startElement - - void openDirectory(const std::string& dirName) - { - if (dirName.empty()) { - // root directory, we shall assume - currentDir = tree->rootDir(); - } else { - assert(currentDir); - currentDir = currentDir->child(dirName); - } - - assert(currentDir); - currentPath = currentDir->fsPath(); - currentDir->beginUpdateReport(); - } - - void deleteEntry(const std::string& entryName) - { - currentDir->deleteChildByName(entryName); - } - - bool decodeTextDelta(const SGPath& outputPath) - { - std::vector output, decoded; - strutils::decodeBase64(txDeltaData, decoded); - size_t bytesToDecode = decoded.size(); - - unsigned char* p = decoded.data(); - if (memcmp(p, "SVN\0", DELTA_HEADER_SIZE) != 0) { - return false; // bad header - } - - bytesToDecode -= DELTA_HEADER_SIZE; - p += DELTA_HEADER_SIZE; - std::ifstream source; - source.open(outputPath.c_str(), std::ios::in | std::ios::binary); - - while (bytesToDecode > 0) { - if (!SVNDeltaWindow::isWindowComplete(p, bytesToDecode)) { - SG_LOG(SG_IO, SG_WARN, "SVN txdelta broken window"); - return false; - } - - SVNDeltaWindow window(p); - assert(bytesToDecode >= window.size()); - window.apply(output, source); - bytesToDecode -= window.size(); - p += window.size(); - } - - source.close(); - - std::ofstream f; - f.open(outputPath.c_str(), - std::ios::out | std::ios::trunc | std::ios::binary); - f.write((char*) output.data(), output.size()); - - // compute MD5 while we have the file in memory - memset(&md5Context, 0, sizeof(SG_MD5_CTX)); - SG_MD5Init(&md5Context); - SG_MD5Update(&md5Context, (unsigned char*) output.data(), output.size()); - unsigned char digest[MD5_DIGEST_LENGTH]; - SG_MD5Final(digest, &md5Context); - decodedFileMd5 = strutils::encodeHex(digest, MD5_DIGEST_LENGTH); - - return true; - } - - void endElement (const char * name) - { - if (status != SVNRepository::REPO_NO_ERROR) { - return; - } - - assert(tagStack.back() == name); - tagStack.pop_back(); - - if (!strcmp(name, SVN_TXDELTA_TAG)) { - if (!decodeTextDelta(currentPath)) { - fail(SVNRepository::SVN_ERROR_TXDELTA); - } - } else if (!strcmp(name, SVN_ADD_FILE_TAG)) { - finishFile(currentPath); - } else if (!strcmp(name, SVN_OPEN_FILE_TAG)) { - finishFile(currentPath); - } else if (!strcmp(name, SVN_ADD_DIRECTORY_TAG)) { - // pop directory - currentPath = currentPath.dir(); - currentDir->updateReportComplete(); - currentDir = currentDir->parent(); - } else if (!strcmp(name, SVN_SET_PROP_TAG)) { - if (setPropName == "svn:entry:committed-rev") { - revision = strutils::to_int(setPropValue); - currentVersionName = setPropValue; - if (!inFile) { - // for directories we have the resource already - // for adding files, we might not; we set the version name - // above when ending the add/open-file element - currentDir->collection()->setVersionName(currentVersionName); - } - } - } else if (!strcmp(name, SVN_DAV_MD5_CHECKSUM)) { - // validate against (presumably) just written file - if (decodedFileMd5 != md5Sum) { - fail(SVNRepository::REPO_ERROR_CHECKSUM); - } - } else if (!strcmp(name, SVN_OPEN_DIRECTORY_TAG)) { - currentDir->updateReportComplete(); - if (currentDir->parent()) { - // pop the collection stack - currentDir = currentDir->parent(); - } - - currentPath = currentDir->fsPath(); - } else { - // std::cout << "element:" << name; - } - } - - void finishFile(const SGPath& path) - { - currentPath = path.dir(); - inFile = false; - } - - void data (const char * s, int length) - { - if (status != SVNRepository::REPO_NO_ERROR) { - return; - } - - if (tagStack.back() == SVN_SET_PROP_TAG) { - setPropValue.append(s, length); - } else if (tagStack.back() == SVN_TXDELTA_TAG) { - txDeltaData.append(s, length); - } else if (tagStack.back() == SVN_DAV_MD5_CHECKSUM) { - md5Sum.append(s, length); - } - } - - void pi (const char * target, const char * data) {} - - string tagN(const unsigned int n) const - { - size_t sz = tagStack.size(); - if (n >= sz) { - return string(); - } - - return tagStack[sz - (1 + n)]; - } - - void fail(SVNRepository::ResultCode err) - { - status = err; - } - - SVNRepository* tree; - DAVCollection* rootCollection; - SVNDirectory* currentDir; - SVNRepository::ResultCode status; - - bool parserInited; - XML_Parser xmlParser; - -// in-flight data - string_list tagStack; - string currentVersionName; - string txDeltaData; - SGPath currentPath; - bool inFile; - - unsigned int revision; - SG_MD5_CTX md5Context; - string md5Sum, decodedFileMd5; - std::string setPropName, setPropValue; -}; - - -//////////////////////////////////////////////////////////////////////// -// Static callback functions for Expat. -//////////////////////////////////////////////////////////////////////// - -#define VISITOR static_cast(userData) - -static void -start_element (void * userData, const char * name, const char ** atts) -{ - VISITOR->startElement(name, atts); -} - -static void -end_element (void * userData, const char * name) -{ - VISITOR->endElement(name); -} - -static void -character_data (void * userData, const char * s, int len) -{ - VISITOR->data(s, len); -} - -static void -processing_instruction (void * userData, - const char * target, - const char * data) -{ - VISITOR->pi(target, data); -} - -#undef VISITOR - -/////////////////////////////////////////////////////////////////////////////// - -SVNReportParser::SVNReportParser(SVNRepository* repo) : - _d(new SVNReportParserPrivate(repo)) -{ - -} - -SVNReportParser::~SVNReportParser() -{ -} - -SVNRepository::ResultCode -SVNReportParser::innerParseXML(const char* data, int size) -{ - if (_d->status != SVNRepository::REPO_NO_ERROR) { - return _d->status; - } - - bool isEnd = (data == NULL); - if (!XML_Parse(_d->xmlParser, data, size, isEnd)) { - SG_LOG(SG_IO, SG_INFO, "SVN parse error:" << XML_ErrorString(XML_GetErrorCode(_d->xmlParser)) - << " at line:" << XML_GetCurrentLineNumber(_d->xmlParser) - << " column " << XML_GetCurrentColumnNumber(_d->xmlParser)); - - XML_ParserFree(_d->xmlParser); - _d->parserInited = false; - return SVNRepository::SVN_ERROR_XML; - } else if (isEnd) { - XML_ParserFree(_d->xmlParser); - _d->parserInited = false; - } - - return _d->status; -} - -SVNRepository::ResultCode -SVNReportParser::parseXML(const char* data, int size) -{ - if (_d->status != SVNRepository::REPO_NO_ERROR) { - return _d->status; - } - - if (!_d->parserInited) { - _d->xmlParser = XML_ParserCreateNS(0, ':'); - XML_SetUserData(_d->xmlParser, _d.get()); - XML_SetElementHandler(_d->xmlParser, start_element, end_element); - XML_SetCharacterDataHandler(_d->xmlParser, character_data); - XML_SetProcessingInstructionHandler(_d->xmlParser, processing_instruction); - _d->parserInited = true; - } - - return innerParseXML(data, size); -} - -SVNRepository::ResultCode SVNReportParser::finishParse() -{ - if (_d->status != SVNRepository::REPO_NO_ERROR) { - return _d->status; - } - - return innerParseXML(NULL, 0); -} - -std::string SVNReportParser::etagFromRevision(unsigned int revision) -{ - // etags look like W/"7//", hopefully this is stable - // across different servers and similar - std::ostringstream os; - os << "W/\"" << revision << "//"; - return os.str(); -} - - diff --git a/simgear/io/SVNReportParser.hxx b/simgear/io/SVNReportParser.hxx deleted file mode 100644 index 1e94751b..00000000 --- a/simgear/io/SVNReportParser.hxx +++ /dev/null @@ -1,57 +0,0 @@ -// SVNReportParser -- parser for SVN report XML data -// -// Copyright (C) 2012 James Turner -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - -#ifndef SG_IO_SVNREPORTPARSER_HXX -#define SG_IO_SVNREPORTPARSER_HXX - -#include -#include // for auto_ptr - -#include "SVNRepository.hxx" - -class SGPath; - -namespace simgear -{ - -class SVNRepository; - -class SVNReportParser -{ -public: - SVNReportParser(SVNRepository* repo); - ~SVNReportParser(); - - // incremental XML parsing - SVNRepository::ResultCode parseXML(const char* data, int size); - - SVNRepository::ResultCode finishParse(); - - static std::string etagFromRevision(unsigned int revision); - - class SVNReportParserPrivate; -private: - SVNRepository::ResultCode innerParseXML(const char* data, int size); - - std::auto_ptr _d; -}; - -} // of namespace simgear - -#endif // of SG_IO_SVNREPORTPARSER_HXX diff --git a/simgear/io/SVNRepository.cxx b/simgear/io/SVNRepository.cxx deleted file mode 100644 index 033fa9ef..00000000 --- a/simgear/io/SVNRepository.cxx +++ /dev/null @@ -1,386 +0,0 @@ -// DAVMirrorTree -- mirror a DAV tree to the local file-system -// -// Copyright (C) 2012 James Turner -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -#include "SVNRepository.hxx" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "simgear/debug/logstream.hxx" -#include "simgear/misc/strutils.hxx" -#include -#include -#include -#include -#include -#include - -using std::cout; -using std::cerr; -using std::endl; -using std::string; - -namespace simgear -{ - -typedef std::vector RequestVector; - -class SVNRepoPrivate -{ -public: - SVNRepoPrivate(SVNRepository* parent) : - p(parent), - isUpdating(false), - status(SVNRepository::REPO_NO_ERROR) - { ; } - - SVNRepository* p; // link back to outer - SVNDirectory* rootCollection; - HTTP::Client* http; - std::string baseUrl; - std::string vccUrl; - std::string targetRevision; - bool isUpdating; - SVNRepository::ResultCode status; - - void svnUpdateDone() - { - isUpdating = false; - } - - void updateFailed(HTTP::Request* req, SVNRepository::ResultCode err) - { - SG_LOG(SG_TERRASYNC, SG_WARN, "SVN: failed to update from:" << req->url() - << "\n(repository:" << p->baseUrl() << ")"); - isUpdating = false; - status = err; - } - - void propFindComplete(HTTP::Request* req, DAVCollection* col); - void propFindFailed(HTTP::Request* req, SVNRepository::ResultCode err); -}; - - -namespace { // anonmouse - - string makeAbsoluteUrl(const string& url, const string& base) - { - if (strutils::starts_with(url, "http://")) - return url; // already absolute - - assert(strutils::starts_with(base, "http://")); - int schemeEnd = base.find("://"); - int hostEnd = base.find('/', schemeEnd + 3); - if (hostEnd < 0) { - return url; - } - - return base.substr(0, hostEnd) + url; - } - - // keep the responses small by only requesting the properties we actually - // care about; the ETag, length and MD5-sum - const char* PROPFIND_REQUEST_BODY = - "" - "" - "" - "" - "" - "" - "" - ""; - - class PropFindRequest : public HTTP::Request - { - public: - PropFindRequest(SVNRepoPrivate* repo) : - Request(repo->baseUrl, "PROPFIND"), - _repo(repo) - { - assert(repo); - requestHeader("Depth") = "0"; - setBodyData( PROPFIND_REQUEST_BODY, - "application/xml; charset=\"utf-8\"" ); - } - - protected: - virtual void responseHeadersComplete() - { - if (responseCode() == 207) { - // fine - } else if (responseCode() == 404) { - _repo->propFindFailed(this, SVNRepository::REPO_ERROR_NOT_FOUND); - } else { - SG_LOG(SG_TERRASYNC, SG_WARN, "request for:" << url() << - " return code " << responseCode()); - _repo->propFindFailed(this, SVNRepository::REPO_ERROR_SOCKET); - _repo = NULL; - } - - Request::responseHeadersComplete(); - } - - virtual void onDone() - { - if (responseCode() == 207) { - _davStatus.finishParse(); - if (_davStatus.isValid()) { - _repo->propFindComplete(this, (DAVCollection*) _davStatus.resource()); - } else { - _repo->propFindFailed(this, SVNRepository::REPO_ERROR_SOCKET); - } - } - } - - virtual void gotBodyData(const char* s, int n) - { - if (responseCode() != 207) { - return; - } - _davStatus.parseXML(s, n); - } - - virtual void onFail() - { - HTTP::Request::onFail(); - if (_repo) { - _repo->propFindFailed(this, SVNRepository::REPO_ERROR_SOCKET); - _repo = NULL; - } - } - - private: - SVNRepoPrivate* _repo; - DAVMultiStatus _davStatus; - }; - -class UpdateReportRequest: - public HTTP::Request -{ -public: - UpdateReportRequest(SVNRepoPrivate* repo, - const std::string& aVersionName, - bool startEmpty) : - HTTP::Request("", "REPORT"), - _parser(repo->p), - _repo(repo), - _failed(false) - { - setUrl(repo->vccUrl); - std::string request = - "\n" - "\n" - "" + repo->baseUrl + "\n" - "unknown\n" - "\n"; - - if( !startEmpty ) - { - string_list entries; - _repo->rootCollection->mergeUpdateReportDetails(0, entries); - BOOST_FOREACH(string e, entries) - { - request += e + "\n"; - } - } - - request += ""; - - setBodyData(request, "application/xml; charset=\"utf-8\""); - } - -protected: - virtual void onDone() - { - if (_failed) { - return; - } - - if (responseCode() == 200) { - SVNRepository::ResultCode err = _parser.finishParse(); - if (err) { - _repo->updateFailed(this, err); - _failed = true; - } else { - _repo->svnUpdateDone(); - } - } else if (responseCode() == 404) { - _repo->updateFailed(this, SVNRepository::REPO_ERROR_NOT_FOUND); - _failed = true; - } else { - SG_LOG(SG_TERRASYNC, SG_WARN, "SVN: request for:" << url() << - " got HTTP status " << responseCode()); - _repo->updateFailed(this, SVNRepository::REPO_ERROR_HTTP); - _failed = true; - } - } - - virtual void gotBodyData(const char* s, int n) - { - if (_failed) { - return; - } - - if (responseCode() != 200) { - return; - } - - SVNRepository::ResultCode err = _parser.parseXML(s, n); - if (err) { - _failed = true; - SG_LOG(SG_IO, SG_WARN, this << ": SVN: request for:" << url() << " failed:" << err); - _repo->updateFailed(this, err); - _repo = NULL; - } - } - - virtual void onFail() - { - HTTP::Request::onFail(); - if (_repo) { - _repo->updateFailed(this, SVNRepository::REPO_ERROR_SOCKET); - _repo = NULL; - } - } -private: - SVNReportParser _parser; - SVNRepoPrivate* _repo; - bool _failed; -}; - -} // anonymous - -SVNRepository::SVNRepository(const SGPath& base, HTTP::Client *cl) : - _d(new SVNRepoPrivate(this)) -{ - _d->http = cl; - _d->rootCollection = new SVNDirectory(this, base); - _d->baseUrl = _d->rootCollection->url(); -} - -SVNRepository::~SVNRepository() -{ - delete _d->rootCollection; -} - -void SVNRepository::setBaseUrl(const std::string &url) -{ - _d->baseUrl = url; - _d->rootCollection->setBaseUrl(url); -} - -std::string SVNRepository::baseUrl() const -{ - return _d->baseUrl; -} - -HTTP::Client* SVNRepository::http() const -{ - return _d->http; -} - -SGPath SVNRepository::fsBase() const -{ - return _d->rootCollection->fsPath(); -} - -bool SVNRepository::isBare() const -{ - if (!fsBase().exists() || Dir(fsBase()).isEmpty()) { - return true; - } - - if (_d->vccUrl.empty()) { - return true; - } - - return false; -} - -void SVNRepository::update() -{ - _d->status = REPO_NO_ERROR; - if (_d->targetRevision.empty() || _d->vccUrl.empty()) { - _d->isUpdating = true; - PropFindRequest* pfr = new PropFindRequest(_d.get()); - http()->makeRequest(pfr); - return; - } - - if (_d->targetRevision == rootDir()->cachedRevision()) { - SG_LOG(SG_TERRASYNC, SG_DEBUG, baseUrl() << " in sync at version " << _d->targetRevision); - _d->isUpdating = false; - return; - } - - _d->isUpdating = true; - UpdateReportRequest* urr = new UpdateReportRequest(_d.get(), - _d->targetRevision, isBare()); - http()->makeRequest(urr); -} - -bool SVNRepository::isDoingSync() const -{ - if (_d->status != REPO_NO_ERROR) { - return false; - } - - return _d->isUpdating || _d->rootCollection->isDoingSync(); -} - -SVNDirectory* SVNRepository::rootDir() const -{ - return _d->rootCollection; -} - -SVNRepository::ResultCode -SVNRepository::failure() const -{ - return _d->status; -} - -/////////////////////////////////////////////////////////////////////////// - -void SVNRepoPrivate::propFindComplete(HTTP::Request* req, DAVCollection* c) -{ - targetRevision = c->versionName(); - vccUrl = makeAbsoluteUrl(c->versionControlledConfiguration(), baseUrl); - rootCollection->collection()->setVersionControlledConfiguration(vccUrl); - p->update(); -} - -void SVNRepoPrivate::propFindFailed(HTTP::Request *req, SVNRepository::ResultCode err) -{ - if (err != SVNRepository::REPO_ERROR_NOT_FOUND) { - SG_LOG(SG_TERRASYNC, SG_WARN, "PropFind failed for:" << req->url()); - } - - isUpdating = false; - status = err; -} - -} // of namespace simgear diff --git a/simgear/io/SVNRepository.hxx b/simgear/io/SVNRepository.hxx deleted file mode 100644 index 3ab4fedc..00000000 --- a/simgear/io/SVNRepository.hxx +++ /dev/null @@ -1,59 +0,0 @@ -// DAVMirrorTree.hxx - mirror a DAV tree to the local file system -// -// Copyright (C) 2012 James Turner -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - -#ifndef SG_IO_SVN_REPOSITORY_HXX -#define SG_IO_SVN_REPOSITORY_HXX - -#include -#include - -namespace simgear { - -class SVNDirectory; -class SVNRepoPrivate; - -class SVNRepository : public AbstractRepository -{ -public: - - SVNRepository(const SGPath& root, HTTP::Client* cl); - virtual ~SVNRepository(); - - SVNDirectory* rootDir() const; - virtual SGPath fsBase() const; - - virtual void setBaseUrl(const std::string& url); - virtual std::string baseUrl() const; - - virtual HTTP::Client* http() const; - - virtual void update(); - - virtual bool isDoingSync() const; - - virtual ResultCode failure() const; -private: - bool isBare() const; - - std::auto_ptr _d; -}; - -} // of namespace simgear - -#endif // of SG_IO_SVN_REPOSITORY_HXX diff --git a/simgear/io/http_svn.cxx b/simgear/io/http_svn.cxx deleted file mode 100644 index f39072d1..00000000 --- a/simgear/io/http_svn.cxx +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include - -#include -#include - - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -using namespace simgear; -using std::cout; -using std::endl; -using std::cerr; -using std::string; - -HTTP::Client* httpClient; - -int main(int argc, char* argv[]) -{ - sglog().setLogLevels( SG_ALL, SG_INFO ); - HTTP::Client cl; - httpClient = &cl; - - - SGPath p("/Users/jmt/Desktop/traffic"); - SVNRepository airports(p, &cl); - // airports.setBaseUrl("http://svn.goneabitbursar.com/testproject1"); -// airports.setBaseUrl("http://terrascenery.googlecode.com/svn/trunk/data/Scenery/Models"); - - airports.setBaseUrl("http://fgfs.goneabitbursar.com/fgfsai/trunk/AI/Traffic"); - -// airports.setBaseUrl("http://terrascenery.googlecode.com/svn/trunk/data/Scenery/Airports"); - airports.update(); - - while (airports.isDoingSync()) { - cl.update(100); - } - - cout << "all done!" << endl; - return EXIT_SUCCESS; -} \ No newline at end of file -- 2.39.5