Package support progress
- check the catalog version explicitly when refreshing - handle packages with distinct dir name / primary ID correctly (requires an updated catalog XML format)
This commit is contained in:
@@ -90,8 +90,13 @@ protected:
|
|||||||
virtual void onDone()
|
virtual void onDone()
|
||||||
{
|
{
|
||||||
if (responseCode() != 200) {
|
if (responseCode() != 200) {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "catalog download failure:" << m_owner->url());
|
Delegate::StatusCode code = Delegate::FAIL_DOWNLOAD;
|
||||||
m_owner->refreshComplete(Delegate::FAIL_DOWNLOAD);
|
SG_LOG(SG_GENERAL, SG_ALERT, "catalog download failure:" << m_owner->url()
|
||||||
|
<< "\n\t" << responseCode());
|
||||||
|
if (responseCode() == 404) {
|
||||||
|
code = Delegate::FAIL_NOT_FOUND;
|
||||||
|
}
|
||||||
|
m_owner->refreshComplete(code);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +111,15 @@ protected:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ver(m_owner->root()->catalogVersion());
|
if (m_owner->root()->catalogVersion() != props->getIntValue("catalog-version")) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_WARN, "catalog:" << m_owner->url() << " is not version "
|
||||||
|
<< m_owner->root()->catalogVersion());
|
||||||
|
m_owner->refreshComplete(Delegate::FAIL_VERSION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string ver(m_owner->root()->applicationVersion());
|
||||||
if (!checkVersion(ver, props)) {
|
if (!checkVersion(ver, props)) {
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "downloaded catalog " << m_owner->url() << ", version mismatch:\n\t"
|
SG_LOG(SG_GENERAL, SG_WARN, "downloaded catalog " << m_owner->url() << ", version mismatch:\n\t"
|
||||||
<< props->getStringValue("version") << " vs required " << ver);
|
<< props->getStringValue("version") << " vs required " << ver);
|
||||||
@@ -186,8 +199,8 @@ CatalogRef Catalog::createFromPath(Root* aRoot, const SGPath& aPath)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkVersion(aRoot->catalogVersion(), props)) {
|
if (!checkVersion(aRoot->applicationVersion(), props)) {
|
||||||
std::string redirect = redirectUrlForVersion(aRoot->catalogVersion(), props);
|
std::string redirect = redirectUrlForVersion(aRoot->applicationVersion(), props);
|
||||||
if (!redirect.empty()) {
|
if (!redirect.empty()) {
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "catalog at " << aPath << ", version mismatch:\n\t"
|
SG_LOG(SG_GENERAL, SG_WARN, "catalog at " << aPath << ", version mismatch:\n\t"
|
||||||
<< "redirecting to alternate URL:" << redirect);
|
<< "redirecting to alternate URL:" << redirect);
|
||||||
@@ -385,11 +398,23 @@ PackageRef Catalog::getPackageById(const std::string& aId) const
|
|||||||
// works as expected.
|
// works as expected.
|
||||||
PackageWeakMap::const_iterator it = m_variantDict.find(aId);
|
PackageWeakMap::const_iterator it = m_variantDict.find(aId);
|
||||||
if (it == m_variantDict.end())
|
if (it == m_variantDict.end())
|
||||||
return NULL;
|
return PackageRef();
|
||||||
|
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PackageRef Catalog::getPackageByPath(const std::string& aPath) const
|
||||||
|
{
|
||||||
|
PackageList::const_iterator it;
|
||||||
|
for (it = m_packages.begin(); it != m_packages.end(); ++it) {
|
||||||
|
if ((*it)->dirName() == aPath) {
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PackageRef();
|
||||||
|
}
|
||||||
|
|
||||||
std::string Catalog::id() const
|
std::string Catalog::id() const
|
||||||
{
|
{
|
||||||
return m_props->getStringValue("id");
|
return m_props->getStringValue("id");
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ public:
|
|||||||
|
|
||||||
PackageRef getPackageById(const std::string& aId) const;
|
PackageRef getPackageById(const std::string& aId) const;
|
||||||
|
|
||||||
|
PackageRef getPackageByPath(const std::string& aPath) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test if the catalog data was retrieved longer ago than the
|
* test if the catalog data was retrieved longer ago than the
|
||||||
* maximum permitted age for this catalog.
|
* maximum permitted age for this catalog.
|
||||||
|
|||||||
@@ -44,11 +44,12 @@ public:
|
|||||||
STATUS_SUCCESS = 0,
|
STATUS_SUCCESS = 0,
|
||||||
FAIL_UNKNOWN = 1,
|
FAIL_UNKNOWN = 1,
|
||||||
STATUS_IN_PROGRESS, ///< downloading/installation in progress
|
STATUS_IN_PROGRESS, ///< downloading/installation in progress
|
||||||
FAIL_CHECKSUM, ///< package MD5 verificstion failed
|
FAIL_CHECKSUM, ///< package MD5 verificstion failed
|
||||||
FAIL_DOWNLOAD, ///< network issue
|
FAIL_DOWNLOAD, ///< network issue
|
||||||
FAIL_EXTRACT, ///< package archive failed to extract cleanly
|
FAIL_EXTRACT, ///< package archive failed to extract cleanly
|
||||||
FAIL_FILESYSTEM, ///< unknown filesystem error occurred
|
FAIL_FILESYSTEM, ///< unknown filesystem error occurred
|
||||||
FAIL_VERSION, ///< version check mismatch
|
FAIL_VERSION, ///< version check mismatch
|
||||||
|
FAIL_NOT_FOUND, ///< package URL returned a 404
|
||||||
STATUS_REFRESHED,
|
STATUS_REFRESHED,
|
||||||
USER_CANCELLED
|
USER_CANCELLED
|
||||||
} StatusCode;
|
} StatusCode;
|
||||||
|
|||||||
@@ -106,8 +106,14 @@ protected:
|
|||||||
virtual void onDone()
|
virtual void onDone()
|
||||||
{
|
{
|
||||||
if (responseCode() != 200) {
|
if (responseCode() != 200) {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "download failure");
|
SG_LOG(SG_GENERAL, SG_ALERT, "download failure:" << responseCode() <<
|
||||||
doFailure(Delegate::FAIL_DOWNLOAD);
|
"\n\t" << url());
|
||||||
|
Delegate::StatusCode code = Delegate::FAIL_DOWNLOAD;
|
||||||
|
if (responseCode() == 404) {
|
||||||
|
code = Delegate::FAIL_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
doFailure(code);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +143,7 @@ protected:
|
|||||||
destDir.remove(true /* recursive */);
|
destDir.remove(true /* recursive */);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_extractPath.append(m_owner->package()->id());
|
m_extractPath.append(m_owner->package()->dirName());
|
||||||
bool ok = m_extractPath.rename(m_owner->path());
|
bool ok = m_extractPath.rename(m_owner->path());
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
doFailure(Delegate::FAIL_FILESYSTEM);
|
doFailure(Delegate::FAIL_FILESYSTEM);
|
||||||
@@ -296,10 +302,10 @@ Install::~Install()
|
|||||||
|
|
||||||
InstallRef Install::createFromPath(const SGPath& aPath, CatalogRef aCat)
|
InstallRef Install::createFromPath(const SGPath& aPath, CatalogRef aCat)
|
||||||
{
|
{
|
||||||
std::string id = aPath.file();
|
std::string path = aPath.file();
|
||||||
PackageRef pkg = aCat->getPackageById(id);
|
PackageRef pkg = aCat->getPackageByPath(path);
|
||||||
if (!pkg)
|
if (!pkg)
|
||||||
throw sg_exception("no package with id:" + id);
|
throw sg_exception("no package with path:" + path);
|
||||||
|
|
||||||
return new Install(pkg, aPath);
|
return new Install(pkg, aPath);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ SGPath Package::pathOnDisk() const
|
|||||||
{
|
{
|
||||||
SGPath p(m_catalog->installRoot());
|
SGPath p(m_catalog->installRoot());
|
||||||
p.append("Aircraft");
|
p.append("Aircraft");
|
||||||
p.append(id());
|
p.append(dirName());
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +139,12 @@ InstallRef Package::install()
|
|||||||
|
|
||||||
InstallRef Package::existingInstall(const InstallCallback& cb) const
|
InstallRef Package::existingInstall(const InstallCallback& cb) const
|
||||||
{
|
{
|
||||||
InstallRef install = m_catalog->root()->existingInstallForPackage(const_cast<Package*>(this));
|
InstallRef install;
|
||||||
|
try {
|
||||||
|
install = m_catalog->root()->existingInstallForPackage(const_cast<Package*>(this));
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
return InstallRef();
|
||||||
|
}
|
||||||
|
|
||||||
if( cb )
|
if( cb )
|
||||||
{
|
{
|
||||||
@@ -167,6 +172,14 @@ std::string Package::md5() const
|
|||||||
return m_props->getStringValue("md5");
|
return m_props->getStringValue("md5");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Package::dirName() const
|
||||||
|
{
|
||||||
|
std::string r(m_props->getStringValue("dir"));
|
||||||
|
if (r.empty())
|
||||||
|
throw sg_exception("missing dir property on catalog package entry for " + m_id);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int Package::revision() const
|
unsigned int Package::revision() const
|
||||||
{
|
{
|
||||||
if (!m_props) {
|
if (!m_props) {
|
||||||
|
|||||||
@@ -133,6 +133,12 @@ public:
|
|||||||
* this will raise an sg_exception.
|
* this will raise an sg_exception.
|
||||||
*/
|
*/
|
||||||
PackageList dependencies() const;
|
PackageList dependencies() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the package directory on disk. This may or may not be the
|
||||||
|
* same as the primary ID, depending on the aircraft author
|
||||||
|
*/
|
||||||
|
std::string dirName() const;
|
||||||
private:
|
private:
|
||||||
SGPath pathOnDisk() const;
|
SGPath pathOnDisk() const;
|
||||||
|
|
||||||
|
|||||||
@@ -247,7 +247,12 @@ Root::~Root()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Root::catalogVersion() const
|
int Root::catalogVersion() const
|
||||||
|
{
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Root::applicationVersion() const
|
||||||
{
|
{
|
||||||
return d->version;
|
return d->version;
|
||||||
}
|
}
|
||||||
@@ -443,8 +448,10 @@ void Root::finishInstall(InstallRef aInstall, Delegate::StatusCode aReason)
|
|||||||
<< aInstall->package()->id() << ":" << aReason);
|
<< aInstall->package()->id() << ":" << aReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
d->fireFinishInstall(aInstall, aReason);
|
// order matters here, so a call to 'isQueued' from a finish-install
|
||||||
|
// callback returns false, not true
|
||||||
startNext(aInstall);
|
startNext(aInstall);
|
||||||
|
d->fireFinishInstall(aInstall, aReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Root::cancelDownload(InstallRef aInstall)
|
void Root::cancelDownload(InstallRef aInstall)
|
||||||
@@ -545,6 +552,9 @@ InstallRef Root::existingInstallForPackage(PackageRef p) const
|
|||||||
return Install::createFromPath(path, p->catalog());
|
return Install::createFromPath(path, p->catalog());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// insert a null reference into the dictionary, so we don't call
|
||||||
|
// the pathOnDisk -> exists codepath repeatedley
|
||||||
|
d->m_installs[p] = InstallRef();
|
||||||
return InstallRef();
|
return InstallRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,10 +83,16 @@ public:
|
|||||||
void makeHTTPRequest(HTTP::Request* req);
|
void makeHTTPRequest(HTTP::Request* req);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the version string of the root. Catalogs must match this version,
|
* The catalog XML/property version in use. This is used to make incomaptible
|
||||||
|
* changes to the package/catalog syntax
|
||||||
|
*/
|
||||||
|
int catalogVersion() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the version string of the application. Catalogs must match this version,
|
||||||
* or they will be ignored / rejected.
|
* or they will be ignored / rejected.
|
||||||
*/
|
*/
|
||||||
std::string catalogVersion() const;
|
std::string applicationVersion() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* refresh catalogs which are more than the maximum age (24 hours by default)
|
* refresh catalogs which are more than the maximum age (24 hours by default)
|
||||||
|
|||||||
Reference in New Issue
Block a user