#include <map>
#include <set>
#include <fstream>
+#include <memory>
#include <boost/foreach.hpp>
class SVNRepoPrivate
{
public:
- SVNRepoPrivate(SVNRepository* parent) :
- p(parent),
+ SVNRepoPrivate(SVNRepository* parent) :
+ p(parent),
isUpdating(false),
- status(SVNRepository::SVN_NO_ERROR)
+ status(SVNRepository::REPO_NO_ERROR)
{ ; }
-
+
SVNRepository* p; // link back to outer
SVNDirectory* rootCollection;
HTTP::Client* http;
std::string targetRevision;
bool isUpdating;
SVNRepository::ResultCode status;
-
+
void svnUpdateDone()
{
isUpdating = false;
}
-
+
void updateFailed(HTTP::Request* req, SVNRepository::ResultCode err)
{
- SG_LOG(SG_IO, SG_WARN, "SVN: failed to update from:" << req->url()
+ 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 =
Request(repo->baseUrl, "PROPFIND"),
_repo(repo)
{
+ assert(repo);
requestHeader("Depth") = "0";
setBodyData( PROPFIND_REQUEST_BODY,
"application/xml; charset=\"utf-8\"" );
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_IO, SG_WARN, "request for:" << url() <<
+ 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;
}
+
+ Request::responseHeadersComplete();
}
-
+
virtual void onDone()
{
if (responseCode() == 207) {
if (_davStatus.isValid()) {
_repo->propFindComplete(this, (DAVCollection*) _davStatus.resource());
} else {
- _repo->propFindFailed(this, SVNRepository::SVN_ERROR_SOCKET);
+ _repo->propFindFailed(this, SVNRepository::REPO_ERROR_SOCKET);
}
}
}
-
+
virtual void gotBodyData(const char* s, int n)
{
if (responseCode() != 207) {
}
_davStatus.parseXML(s, n);
}
-
+
virtual void onFail()
{
HTTP::Request::onFail();
if (_repo) {
- _repo->propFindFailed(this, SVNRepository::SVN_ERROR_SOCKET);
+ _repo->propFindFailed(this, SVNRepository::REPO_ERROR_SOCKET);
_repo = NULL;
}
}
-
+
private:
SVNRepoPrivate* _repo;
DAVMultiStatus _davStatus;
public HTTP::Request
{
public:
- UpdateReportRequest(SVNRepoPrivate* repo,
+ 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 =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
if (_failed) {
return;
}
-
+
if (responseCode() == 200) {
SVNRepository::ResultCode err = _parser.finishParse();
if (err) {
_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_IO, SG_WARN, "SVN: request for:" << url() <<
- " return code " << responseCode());
- _repo->updateFailed(this, SVNRepository::SVN_ERROR_SOCKET);
+ 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, _repo->p << ": SVN: request for:" << url() << " failed:" << err);
+ SG_LOG(SG_IO, SG_WARN, this << ": SVN: request for:" << url() << " failed:" << err);
_repo->updateFailed(this, err);
_repo = NULL;
}
{
HTTP::Request::onFail();
if (_repo) {
- _repo->updateFailed(this, SVNRepository::SVN_ERROR_SOCKET);
+ _repo->updateFailed(this, SVNRepository::REPO_ERROR_SOCKET);
_repo = NULL;
}
}
SVNRepoPrivate* _repo;
bool _failed;
};
-
-} // anonymous
+
+} // 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);
- _d->baseUrl = _d->rootCollection->url();
+ _d->baseUrl = _d->rootCollection->url();
}
SVNRepository::~SVNRepository()
if (!fsBase().exists() || Dir(fsBase()).isEmpty()) {
return true;
}
-
+
if (_d->vccUrl.empty()) {
return true;
}
-
+
return false;
}
void SVNRepository::update()
-{
- _d->status = SVN_NO_ERROR;
- if (_d->targetRevision.empty() || _d->vccUrl.empty()) {
- _d->isUpdating = true;
+{
+ _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_IO, SG_DEBUG, baseUrl() << " in sync at version " << _d->targetRevision);
+ 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(),
+ UpdateReportRequest* urr = new UpdateReportRequest(_d.get(),
_d->targetRevision, isBare());
http()->makeRequest(urr);
}
-
+
bool SVNRepository::isDoingSync() const
{
- if (_d->status != SVN_NO_ERROR) {
+ if (_d->status != REPO_NO_ERROR) {
return false;
}
-
+
return _d->isUpdating || _d->rootCollection->isDoingSync();
}
{
targetRevision = c->versionName();
vccUrl = makeAbsoluteUrl(c->versionControlledConfiguration(), baseUrl);
- rootCollection->collection()->setVersionControlledConfiguration(vccUrl);
+ rootCollection->collection()->setVersionControlledConfiguration(vccUrl);
p->update();
}
-
+
void SVNRepoPrivate::propFindFailed(HTTP::Request *req, SVNRepository::ResultCode err)
{
- if (err != SVNRepository::SVN_ERROR_NOT_FOUND) {
- SG_LOG(SG_IO, SG_WARN, "PropFind failed for:" << req->url());
+ if (err != SVNRepository::REPO_ERROR_NOT_FOUND) {
+ SG_LOG(SG_TERRASYNC, SG_WARN, "PropFind failed for:" << req->url());
}
-
+
isUpdating = false;
status = err;
}