Terrasync: update fixes.
- Fix a nasty issue when updating existing repositories, which could cause repository corruption and hence repeated re-syncs.
This commit is contained in:
@@ -106,12 +106,13 @@ namespace {
|
|||||||
const char* SVN_ADD_FILE_TAG = SVN_NS "add-file";
|
const char* SVN_ADD_FILE_TAG = SVN_NS "add-file";
|
||||||
const char* SVN_TXDELTA_TAG = SVN_NS "txdelta";
|
const char* SVN_TXDELTA_TAG = SVN_NS "txdelta";
|
||||||
const char* SVN_SET_PROP_TAG = SVN_NS "set-prop";
|
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_DELETE_ENTRY_TAG = SVN_NS "delete-entry";
|
||||||
|
|
||||||
const char* SVN_DAV_MD5_CHECKSUM = SUBVERSION_DAV_NS ":md5-checksum";
|
const char* SVN_DAV_MD5_CHECKSUM = SUBVERSION_DAV_NS ":md5-checksum";
|
||||||
|
|
||||||
const char* DAV_HREF_TAG = DAV_NS "href";
|
const char* DAV_HREF_TAG = DAV_NS "href";
|
||||||
const char* DAV_CHECKED_IN_TAG = SVN_NS "checked-in";
|
const char* DAV_CHECKED_IN_TAG = DAV_NS "checked-in";
|
||||||
|
|
||||||
|
|
||||||
const int svn_txdelta_source = 0;
|
const int svn_txdelta_source = 0;
|
||||||
@@ -173,7 +174,7 @@ namespace {
|
|||||||
while (_ptr < pEnd) {
|
while (_ptr < pEnd) {
|
||||||
int op = ((*_ptr >> 6) & 0x3);
|
int op = ((*_ptr >> 6) & 0x3);
|
||||||
if (op >= 3) {
|
if (op >= 3) {
|
||||||
SG_LOG(SG_IO, SG_INFO, "SVNDeltaWindow: bad opcode:" << op);
|
SG_LOG(SG_IO, SG_INFO, "SVNDeltaWindow: bad opcode:" << op);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,12 +196,14 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (op == svn_txdelta_target) {
|
if (op == svn_txdelta_target) {
|
||||||
while (length > 0) {
|
// this is inefficent, but ranges can overlap.
|
||||||
output.push_back(output[offset++]);
|
while (length > 0) {
|
||||||
--length;
|
output.push_back(output[offset++]);
|
||||||
}
|
--length;
|
||||||
|
}
|
||||||
} else if (op == svn_txdelta_new) {
|
} else if (op == svn_txdelta_new) {
|
||||||
output.insert(output.end(), newData, newData + length);
|
output.insert(output.end(), newData, newData + length);
|
||||||
|
newData += length;
|
||||||
} else if (op == svn_txdelta_source) {
|
} else if (op == svn_txdelta_source) {
|
||||||
source.seekg(offset);
|
source.seekg(offset);
|
||||||
char* sourceBuf = (char*) malloc(length);
|
char* sourceBuf = (char*) malloc(length);
|
||||||
@@ -208,6 +211,9 @@ namespace {
|
|||||||
source.read(sourceBuf, length);
|
source.read(sourceBuf, length);
|
||||||
output.insert(output.end(), sourceBuf, sourceBuf + length);
|
output.insert(output.end(), sourceBuf, sourceBuf + length);
|
||||||
free(sourceBuf);
|
free(sourceBuf);
|
||||||
|
} else {
|
||||||
|
SG_LOG(SG_IO, SG_WARN, "bad opcode logic");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} // of instruction loop
|
} // of instruction loop
|
||||||
|
|
||||||
@@ -269,12 +275,12 @@ public:
|
|||||||
string fileName(attrs.getValue("name"));
|
string fileName(attrs.getValue("name"));
|
||||||
SGPath filePath(Dir(currentPath).file(fileName));
|
SGPath filePath(Dir(currentPath).file(fileName));
|
||||||
currentPath = filePath;
|
currentPath = filePath;
|
||||||
|
|
||||||
DAVResource* res = currentDir->collection()->childWithName(fileName);
|
if (!filePath.exists()) {
|
||||||
if (!res || !filePath.exists()) {
|
fail(SVNRepository::SVN_ERROR_FILE_NOT_FOUND);
|
||||||
// set error condition
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
inFile = true;
|
inFile = true;
|
||||||
} else if (!strcmp(name, SVN_ADD_DIRECTORY_TAG)) {
|
} else if (!strcmp(name, SVN_ADD_DIRECTORY_TAG)) {
|
||||||
string dirName(attrs.getValue("name"));
|
string dirName(attrs.getValue("name"));
|
||||||
@@ -302,10 +308,12 @@ public:
|
|||||||
} else if (!strcmp(name, SVN_DELETE_ENTRY_TAG)) {
|
} else if (!strcmp(name, SVN_DELETE_ENTRY_TAG)) {
|
||||||
string entryName(attrs.getValue("name"));
|
string entryName(attrs.getValue("name"));
|
||||||
deleteEntry(entryName);
|
deleteEntry(entryName);
|
||||||
} else if (!strcmp(name, DAV_CHECKED_IN_TAG) || !strcmp(name, DAV_HREF_TAG)) {
|
} else if (!strcmp(name, DAV_CHECKED_IN_TAG) ||
|
||||||
|
!strcmp(name, DAV_HREF_TAG) ||
|
||||||
|
!strcmp(name, SVN_PROP_TAG)) {
|
||||||
// don't warn on these ones
|
// don't warn on these ones
|
||||||
} else {
|
} else {
|
||||||
//std::cerr << "unhandled element:" << name << std::endl;
|
//SG_LOG(SG_IO, SG_WARN, "SVNReportParser: unhandled tag:" << name);
|
||||||
}
|
}
|
||||||
} // of startElement
|
} // of startElement
|
||||||
|
|
||||||
@@ -389,15 +397,9 @@ public:
|
|||||||
fail(SVNRepository::SVN_ERROR_TXDELTA);
|
fail(SVNRepository::SVN_ERROR_TXDELTA);
|
||||||
}
|
}
|
||||||
} else if (!strcmp(name, SVN_ADD_FILE_TAG)) {
|
} else if (!strcmp(name, SVN_ADD_FILE_TAG)) {
|
||||||
finishFile(currentDir->addChildFile(currentPath.file()));
|
finishFile(currentPath);
|
||||||
} else if (!strcmp(name, SVN_OPEN_FILE_TAG)) {
|
} else if (!strcmp(name, SVN_OPEN_FILE_TAG)) {
|
||||||
DAVResource* res = currentDir->collection()->childWithName(currentPath.file());
|
finishFile(currentPath);
|
||||||
if (!res) {
|
|
||||||
SG_LOG(SG_IO, SG_WARN, "SVN open-file: unknown: " << currentPath);
|
|
||||||
fail(SVNRepository::SVN_ERROR_IO);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
finishFile(res);
|
|
||||||
} else if (!strcmp(name, SVN_ADD_DIRECTORY_TAG)) {
|
} else if (!strcmp(name, SVN_ADD_DIRECTORY_TAG)) {
|
||||||
// pop directory
|
// pop directory
|
||||||
currentPath = currentPath.dir();
|
currentPath = currentPath.dir();
|
||||||
@@ -417,7 +419,6 @@ 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) {
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "checksum fail on:" << currentPath);
|
|
||||||
fail(SVNRepository::SVN_ERROR_CHECKSUM);
|
fail(SVNRepository::SVN_ERROR_CHECKSUM);
|
||||||
}
|
}
|
||||||
} else if (!strcmp(name, SVN_OPEN_DIRECTORY_TAG)) {
|
} else if (!strcmp(name, SVN_OPEN_DIRECTORY_TAG)) {
|
||||||
@@ -433,11 +434,9 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void finishFile(DAVResource* res)
|
void finishFile(const SGPath& path)
|
||||||
{
|
{
|
||||||
res->setVersionName(currentVersionName);
|
currentPath = path.dir();
|
||||||
res->setMD5(md5Sum);
|
|
||||||
currentPath = currentPath.dir();
|
|
||||||
inFile = false;
|
inFile = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -229,8 +229,8 @@ protected:
|
|||||||
_failed = true;
|
_failed = true;
|
||||||
} else {
|
} else {
|
||||||
SG_LOG(SG_IO, SG_WARN, "SVN: request for:" << url() <<
|
SG_LOG(SG_IO, SG_WARN, "SVN: request for:" << url() <<
|
||||||
" return code " << responseCode());
|
" got HTTP status " << responseCode());
|
||||||
_repo->updateFailed(this, SVNRepository::SVN_ERROR_SOCKET);
|
_repo->updateFailed(this, SVNRepository::SVN_ERROR_HTTP);
|
||||||
_failed = true;
|
_failed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,7 +248,7 @@ protected:
|
|||||||
SVNRepository::ResultCode err = _parser.parseXML(s, n);
|
SVNRepository::ResultCode err = _parser.parseXML(s, n);
|
||||||
if (err) {
|
if (err) {
|
||||||
_failed = true;
|
_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->updateFailed(this, err);
|
||||||
_repo = NULL;
|
_repo = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,9 @@ public:
|
|||||||
SVN_ERROR_XML,
|
SVN_ERROR_XML,
|
||||||
SVN_ERROR_TXDELTA,
|
SVN_ERROR_TXDELTA,
|
||||||
SVN_ERROR_IO,
|
SVN_ERROR_IO,
|
||||||
SVN_ERROR_CHECKSUM
|
SVN_ERROR_CHECKSUM,
|
||||||
|
SVN_ERROR_FILE_NOT_FOUND,
|
||||||
|
SVN_ERROR_HTTP
|
||||||
};
|
};
|
||||||
|
|
||||||
ResultCode failure() const;
|
ResultCode failure() const;
|
||||||
|
|||||||
Reference in New Issue
Block a user