Create TerraSync repo API

- create an abstract API for a remote repository, based on the current
  SVN repository API, and update the code accordingly.
This commit is contained in:
James Turner 2016-01-25 18:15:48 -06:00
parent e7598df4d3
commit 7075a8707b
7 changed files with 142 additions and 62 deletions

View File

@ -0,0 +1,29 @@
// AbstractRepository.cxx -- abstract API for TerraSync remote
//
// Copyright (C) 2016 James Turner <zakalawe@mac.com>
//
// 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 "AbstractRepository.hxx"
namespace simgear
{
AbstractRepository::~AbstractRepository()
{
}
} // of namespace simgear

View File

@ -0,0 +1,69 @@
// AbstractRepository.hxx - API for terrasyc to access remote server
//
// Copyright (C) 2016 James Turner <zakalawe@mac.com>
//
// 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_ABSTRACT_REPOSITORY_HXX
#define SG_IO_ABSTRACT_REPOSITORY_HXX
#include <string>
#include <simgear/misc/sg_path.hxx>
namespace simgear {
namespace HTTP {
class Client;
}
class AbstractRepository
{
public:
virtual ~AbstractRepository();
virtual SGPath fsBase() const = 0;
virtual void setBaseUrl(const std::string& url) =0;
virtual std::string baseUrl() const = 0;;
virtual HTTP::Client* http() const = 0;
virtual void update() = 0;
virtual bool isDoingSync() const = 0;
enum ResultCode {
REPO_NO_ERROR = 0,
REPO_ERROR_NOT_FOUND,
REPO_ERROR_SOCKET,
SVN_ERROR_XML,
SVN_ERROR_TXDELTA,
REPO_ERROR_IO,
REPO_ERROR_CHECKSUM,
REPO_ERROR_FILE_NOT_FOUND,
REPO_ERROR_HTTP
};
virtual ResultCode failure() const = 0;
protected:
};
} // of namespace simgear
#endif // of SG_IO_ABSTRACT_REPOSITORY_HXX

View File

@ -18,6 +18,7 @@ set(HEADERS
HTTPFileRequest.hxx HTTPFileRequest.hxx
HTTPMemoryRequest.hxx HTTPMemoryRequest.hxx
HTTPRequest.hxx HTTPRequest.hxx
AbstractRepository.hxx
DAVMultiStatus.hxx DAVMultiStatus.hxx
SVNRepository.hxx SVNRepository.hxx
SVNDirectory.hxx SVNDirectory.hxx
@ -40,6 +41,7 @@ set(SOURCES
HTTPFileRequest.cxx HTTPFileRequest.cxx
HTTPMemoryRequest.cxx HTTPMemoryRequest.cxx
HTTPRequest.cxx HTTPRequest.cxx
AbstractRepository.cxx
DAVMultiStatus.cxx DAVMultiStatus.cxx
SVNRepository.cxx SVNRepository.cxx
SVNDirectory.cxx SVNDirectory.cxx

View File

@ -244,7 +244,7 @@ class SVNReportParser::SVNReportParserPrivate
public: public:
SVNReportParserPrivate(SVNRepository* repo) : SVNReportParserPrivate(SVNRepository* repo) :
tree(repo), tree(repo),
status(SVNRepository::SVN_NO_ERROR), status(AbstractRepository::REPO_NO_ERROR),
parserInited(false), parserInited(false),
currentPath(repo->fsBase()) currentPath(repo->fsBase())
{ {
@ -258,7 +258,7 @@ public:
void startElement (const char * name, const char** attributes) void startElement (const char * name, const char** attributes)
{ {
if (status != SVNRepository::SVN_NO_ERROR) { if (status != AbstractRepository::REPO_NO_ERROR) {
return; return;
} }
@ -277,7 +277,7 @@ public:
currentPath = filePath; currentPath = filePath;
if (!filePath.exists()) { if (!filePath.exists()) {
fail(SVNRepository::SVN_ERROR_FILE_NOT_FOUND); fail(AbstractRepository::REPO_ERROR_FILE_NOT_FOUND);
return; return;
} }
@ -386,7 +386,7 @@ public:
void endElement (const char * name) void endElement (const char * name)
{ {
if (status != SVNRepository::SVN_NO_ERROR) { if (status != SVNRepository::REPO_NO_ERROR) {
return; return;
} }
@ -420,7 +420,7 @@ public:
} else if (!strcmp(name, SVN_DAV_MD5_CHECKSUM)) { } else if (!strcmp(name, SVN_DAV_MD5_CHECKSUM)) {
// validate against (presumably) just written file // validate against (presumably) just written file
if (decodedFileMd5 != md5Sum) { if (decodedFileMd5 != md5Sum) {
fail(SVNRepository::SVN_ERROR_CHECKSUM); fail(SVNRepository::REPO_ERROR_CHECKSUM);
} }
} else if (!strcmp(name, SVN_OPEN_DIRECTORY_TAG)) { } else if (!strcmp(name, SVN_OPEN_DIRECTORY_TAG)) {
currentDir->updateReportComplete(); currentDir->updateReportComplete();
@ -443,7 +443,7 @@ public:
void data (const char * s, int length) void data (const char * s, int length)
{ {
if (status != SVNRepository::SVN_NO_ERROR) { if (status != SVNRepository::REPO_NO_ERROR) {
return; return;
} }
@ -544,7 +544,7 @@ SVNReportParser::~SVNReportParser()
SVNRepository::ResultCode SVNRepository::ResultCode
SVNReportParser::innerParseXML(const char* data, int size) SVNReportParser::innerParseXML(const char* data, int size)
{ {
if (_d->status != SVNRepository::SVN_NO_ERROR) { if (_d->status != SVNRepository::REPO_NO_ERROR) {
return _d->status; return _d->status;
} }
@ -568,7 +568,7 @@ SVNReportParser::innerParseXML(const char* data, int size)
SVNRepository::ResultCode SVNRepository::ResultCode
SVNReportParser::parseXML(const char* data, int size) SVNReportParser::parseXML(const char* data, int size)
{ {
if (_d->status != SVNRepository::SVN_NO_ERROR) { if (_d->status != SVNRepository::REPO_NO_ERROR) {
return _d->status; return _d->status;
} }
@ -586,7 +586,7 @@ SVNReportParser::parseXML(const char* data, int size)
SVNRepository::ResultCode SVNReportParser::finishParse() SVNRepository::ResultCode SVNReportParser::finishParse()
{ {
if (_d->status != SVNRepository::SVN_NO_ERROR) { if (_d->status != SVNRepository::REPO_NO_ERROR) {
return _d->status; return _d->status;
} }

View File

@ -54,7 +54,7 @@ public:
SVNRepoPrivate(SVNRepository* parent) : SVNRepoPrivate(SVNRepository* parent) :
p(parent), p(parent),
isUpdating(false), isUpdating(false),
status(SVNRepository::SVN_NO_ERROR) status(SVNRepository::REPO_NO_ERROR)
{ ; } { ; }
SVNRepository* p; // link back to outer SVNRepository* p; // link back to outer
@ -132,11 +132,11 @@ namespace { // anonmouse
if (responseCode() == 207) { if (responseCode() == 207) {
// fine // fine
} else if (responseCode() == 404) { } else if (responseCode() == 404) {
_repo->propFindFailed(this, SVNRepository::SVN_ERROR_NOT_FOUND); _repo->propFindFailed(this, SVNRepository::REPO_ERROR_NOT_FOUND);
} else { } else {
SG_LOG(SG_TERRASYNC, SG_WARN, "request for:" << url() << SG_LOG(SG_TERRASYNC, SG_WARN, "request for:" << url() <<
" return code " << responseCode()); " return code " << responseCode());
_repo->propFindFailed(this, SVNRepository::SVN_ERROR_SOCKET); _repo->propFindFailed(this, SVNRepository::REPO_ERROR_SOCKET);
_repo = NULL; _repo = NULL;
} }
@ -150,7 +150,7 @@ namespace { // anonmouse
if (_davStatus.isValid()) { if (_davStatus.isValid()) {
_repo->propFindComplete(this, (DAVCollection*) _davStatus.resource()); _repo->propFindComplete(this, (DAVCollection*) _davStatus.resource());
} else { } else {
_repo->propFindFailed(this, SVNRepository::SVN_ERROR_SOCKET); _repo->propFindFailed(this, SVNRepository::REPO_ERROR_SOCKET);
} }
} }
} }
@ -167,7 +167,7 @@ namespace { // anonmouse
{ {
HTTP::Request::onFail(); HTTP::Request::onFail();
if (_repo) { if (_repo) {
_repo->propFindFailed(this, SVNRepository::SVN_ERROR_SOCKET); _repo->propFindFailed(this, SVNRepository::REPO_ERROR_SOCKET);
_repo = NULL; _repo = NULL;
} }
} }
@ -228,12 +228,12 @@ protected:
_repo->svnUpdateDone(); _repo->svnUpdateDone();
} }
} else if (responseCode() == 404) { } else if (responseCode() == 404) {
_repo->updateFailed(this, SVNRepository::SVN_ERROR_NOT_FOUND); _repo->updateFailed(this, SVNRepository::REPO_ERROR_NOT_FOUND);
_failed = true; _failed = true;
} else { } else {
SG_LOG(SG_TERRASYNC, SG_WARN, "SVN: request for:" << url() << SG_LOG(SG_TERRASYNC, SG_WARN, "SVN: request for:" << url() <<
" got HTTP status " << responseCode()); " got HTTP status " << responseCode());
_repo->updateFailed(this, SVNRepository::SVN_ERROR_HTTP); _repo->updateFailed(this, SVNRepository::REPO_ERROR_HTTP);
_failed = true; _failed = true;
} }
} }
@ -261,7 +261,7 @@ protected:
{ {
HTTP::Request::onFail(); HTTP::Request::onFail();
if (_repo) { if (_repo) {
_repo->updateFailed(this, SVNRepository::SVN_ERROR_SOCKET); _repo->updateFailed(this, SVNRepository::REPO_ERROR_SOCKET);
_repo = NULL; _repo = NULL;
} }
} }
@ -274,7 +274,7 @@ private:
} // anonymous } // anonymous
SVNRepository::SVNRepository(const SGPath& base, HTTP::Client *cl) : SVNRepository::SVNRepository(const SGPath& base, HTTP::Client *cl) :
_d(new SVNRepoPrivate(this)) _d(new SVNRepoPrivate(this))
{ {
_d->http = cl; _d->http = cl;
_d->rootCollection = new SVNDirectory(this, base); _d->rootCollection = new SVNDirectory(this, base);
@ -322,7 +322,7 @@ bool SVNRepository::isBare() const
void SVNRepository::update() void SVNRepository::update()
{ {
_d->status = SVN_NO_ERROR; _d->status = REPO_NO_ERROR;
if (_d->targetRevision.empty() || _d->vccUrl.empty()) { if (_d->targetRevision.empty() || _d->vccUrl.empty()) {
_d->isUpdating = true; _d->isUpdating = true;
PropFindRequest* pfr = new PropFindRequest(_d.get()); PropFindRequest* pfr = new PropFindRequest(_d.get());
@ -344,7 +344,7 @@ void SVNRepository::update()
bool SVNRepository::isDoingSync() const bool SVNRepository::isDoingSync() const
{ {
if (_d->status != SVN_NO_ERROR) { if (_d->status != REPO_NO_ERROR) {
return false; return false;
} }
@ -374,7 +374,7 @@ void SVNRepoPrivate::propFindComplete(HTTP::Request* req, DAVCollection* c)
void SVNRepoPrivate::propFindFailed(HTTP::Request *req, SVNRepository::ResultCode err) void SVNRepoPrivate::propFindFailed(HTTP::Request *req, SVNRepository::ResultCode err)
{ {
if (err != SVNRepository::SVN_ERROR_NOT_FOUND) { if (err != SVNRepository::REPO_ERROR_NOT_FOUND) {
SG_LOG(SG_TERRASYNC, SG_WARN, "PropFind failed for:" << req->url()); SG_LOG(SG_TERRASYNC, SG_WARN, "PropFind failed for:" << req->url());
} }

View File

@ -17,62 +17,42 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef SG_IO_DAVMIRRORTREE_HXX #ifndef SG_IO_SVN_REPOSITORY_HXX
#define SG_IO_DAVMIRRORTREE_HXX #define SG_IO_SVN_REPOSITORY_HXX
#include <string> #include <simgear/io/AbstractRepository.hxx>
#include <vector>
#include <memory>
#include <simgear/misc/sg_path.hxx>
namespace simgear { namespace simgear {
namespace HTTP { class SVNDirectory;
class Client;
}
class SVNDirectory;
class SVNRepoPrivate; class SVNRepoPrivate;
class SVNRepository class SVNRepository : public AbstractRepository
{ {
public: public:
SVNRepository(const SGPath& root, HTTP::Client* cl); SVNRepository(const SGPath& root, HTTP::Client* cl);
~SVNRepository(); virtual ~SVNRepository();
SVNDirectory* rootDir() const; SVNDirectory* rootDir() const;
SGPath fsBase() const; virtual SGPath fsBase() const;
void setBaseUrl(const std::string& url); virtual void setBaseUrl(const std::string& url);
std::string baseUrl() const; virtual std::string baseUrl() const;
HTTP::Client* http() const; virtual HTTP::Client* http() const;
void update(); virtual void update();
bool isDoingSync() const; virtual bool isDoingSync() const;
enum ResultCode { virtual ResultCode failure() const;
SVN_NO_ERROR = 0,
SVN_ERROR_NOT_FOUND,
SVN_ERROR_SOCKET,
SVN_ERROR_XML,
SVN_ERROR_TXDELTA,
SVN_ERROR_IO,
SVN_ERROR_CHECKSUM,
SVN_ERROR_FILE_NOT_FOUND,
SVN_ERROR_HTTP
};
ResultCode failure() const;
private: private:
bool isBare() const; bool isBare() const;
std::auto_ptr<SVNRepoPrivate> _d; std::auto_ptr<SVNRepoPrivate> _d;
}; };
} // of namespace simgear } // of namespace simgear
#endif // of SG_IO_DAVMIRRORTREE_HXX #endif // of SG_IO_SVN_REPOSITORY_HXX

View File

@ -169,7 +169,7 @@ public:
SyncItem currentItem; SyncItem currentItem;
bool isNewDirectory; bool isNewDirectory;
std::queue<SyncItem> queue; std::queue<SyncItem> queue;
std::auto_ptr<SVNRepository> repository; std::auto_ptr<AbstractRepository> repository;
SGTimeStamp stamp; SGTimeStamp stamp;
bool busy; ///< is the slot working or idle bool busy; ///< is the slot working or idle
@ -617,9 +617,9 @@ void SGTerraSync::SvnThread::updateSyncSlot(SyncSlot &slot)
// check result // check result
SVNRepository::ResultCode res = slot.repository->failure(); SVNRepository::ResultCode res = slot.repository->failure();
if (res == SVNRepository::SVN_ERROR_NOT_FOUND) { if (res == AbstractRepository::REPO_ERROR_NOT_FOUND) {
notFound(slot.currentItem); notFound(slot.currentItem);
} else if (res != SVNRepository::SVN_NO_ERROR) { } else if (res != AbstractRepository::REPO_NO_ERROR) {
fail(slot.currentItem); fail(slot.currentItem);
} else { } else {
updated(slot.currentItem, slot.isNewDirectory); updated(slot.currentItem, slot.isNewDirectory);