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
HTTPMemoryRequest.hxx
HTTPRequest.hxx
AbstractRepository.hxx
DAVMultiStatus.hxx
SVNRepository.hxx
SVNDirectory.hxx
@ -40,6 +41,7 @@ set(SOURCES
HTTPFileRequest.cxx
HTTPMemoryRequest.cxx
HTTPRequest.cxx
AbstractRepository.cxx
DAVMultiStatus.cxx
SVNRepository.cxx
SVNDirectory.cxx

View File

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

View File

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

View File

@ -17,56 +17,36 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef SG_IO_DAVMIRRORTREE_HXX
#define SG_IO_DAVMIRRORTREE_HXX
#ifndef SG_IO_SVN_REPOSITORY_HXX
#define SG_IO_SVN_REPOSITORY_HXX
#include <string>
#include <vector>
#include <memory>
#include <simgear/misc/sg_path.hxx>
#include <simgear/io/AbstractRepository.hxx>
namespace simgear {
namespace HTTP {
class Client;
}
class SVNDirectory;
class SVNRepoPrivate;
class SVNRepository
class SVNRepository : public AbstractRepository
{
public:
SVNRepository(const SGPath& root, HTTP::Client* cl);
~SVNRepository();
virtual ~SVNRepository();
SVNDirectory* rootDir() const;
SGPath fsBase() const;
virtual SGPath fsBase() const;
void setBaseUrl(const std::string& url);
std::string baseUrl() const;
virtual void setBaseUrl(const std::string& url);
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 {
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;
virtual ResultCode failure() const;
private:
bool isBare() const;
@ -75,4 +55,4 @@ private:
} // 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;
bool isNewDirectory;
std::queue<SyncItem> queue;
std::auto_ptr<SVNRepository> repository;
std::auto_ptr<AbstractRepository> repository;
SGTimeStamp stamp;
bool busy; ///< is the slot working or idle
@ -617,9 +617,9 @@ void SGTerraSync::SvnThread::updateSyncSlot(SyncSlot &slot)
// check result
SVNRepository::ResultCode res = slot.repository->failure();
if (res == SVNRepository::SVN_ERROR_NOT_FOUND) {
if (res == AbstractRepository::REPO_ERROR_NOT_FOUND) {
notFound(slot.currentItem);
} else if (res != SVNRepository::SVN_NO_ERROR) {
} else if (res != AbstractRepository::REPO_NO_ERROR) {
fail(slot.currentItem);
} else {
updated(slot.currentItem, slot.isNewDirectory);