virtual void onDone()
{
if (responseCode() != 200) {
- SG_LOG(SG_GENERAL, SG_ALERT, "catalog download failure:" << m_owner->url());
- m_owner->refreshComplete(Delegate::FAIL_DOWNLOAD);
+ Delegate::StatusCode code = 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;
}
- 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)) {
SG_LOG(SG_GENERAL, SG_WARN, "downloaded catalog " << m_owner->url() << ", version mismatch:\n\t"
<< props->getStringValue("version") << " vs required " << ver);
return NULL;
}
- if (!checkVersion(aRoot->catalogVersion(), props)) {
- std::string redirect = redirectUrlForVersion(aRoot->catalogVersion(), props);
+ if (!checkVersion(aRoot->applicationVersion(), props)) {
+ std::string redirect = redirectUrlForVersion(aRoot->applicationVersion(), props);
if (!redirect.empty()) {
SG_LOG(SG_GENERAL, SG_WARN, "catalog at " << aPath << ", version mismatch:\n\t"
<< "redirecting to alternate URL:" << redirect);
// works as expected.
PackageWeakMap::const_iterator it = m_variantDict.find(aId);
if (it == m_variantDict.end())
- return NULL;
+ return PackageRef();
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
{
return m_props->getStringValue("id");
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
* maximum permitted age for this catalog.
STATUS_SUCCESS = 0,
FAIL_UNKNOWN = 1,
STATUS_IN_PROGRESS, ///< downloading/installation in progress
- FAIL_CHECKSUM, ///< package MD5 verificstion failed
- FAIL_DOWNLOAD, ///< network issue
- FAIL_EXTRACT, ///< package archive failed to extract cleanly
+ FAIL_CHECKSUM, ///< package MD5 verificstion failed
+ FAIL_DOWNLOAD, ///< network issue
+ FAIL_EXTRACT, ///< package archive failed to extract cleanly
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,
USER_CANCELLED
} StatusCode;
virtual void onDone()
{
if (responseCode() != 200) {
- SG_LOG(SG_GENERAL, SG_ALERT, "download failure");
- doFailure(Delegate::FAIL_DOWNLOAD);
+ SG_LOG(SG_GENERAL, SG_ALERT, "download failure:" << responseCode() <<
+ "\n\t" << url());
+ Delegate::StatusCode code = Delegate::FAIL_DOWNLOAD;
+ if (responseCode() == 404) {
+ code = Delegate::FAIL_NOT_FOUND;
+ }
+
+ doFailure(code);
return;
}
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());
if (!ok) {
doFailure(Delegate::FAIL_FILESYSTEM);
InstallRef Install::createFromPath(const SGPath& aPath, CatalogRef aCat)
{
- std::string id = aPath.file();
- PackageRef pkg = aCat->getPackageById(id);
+ std::string path = aPath.file();
+ PackageRef pkg = aCat->getPackageByPath(path);
if (!pkg)
- throw sg_exception("no package with id:" + id);
+ throw sg_exception("no package with path:" + path);
return new Install(pkg, aPath);
}
{
SGPath p(m_catalog->installRoot());
p.append("Aircraft");
- p.append(id());
+ p.append(dirName());
return p;
}
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 )
{
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
{
if (!m_props) {
* this will raise an sg_exception.
*/
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:
SGPath pathOnDisk() const;
{
}
+
+int Root::catalogVersion() const
+{
+ return 4;
+}
-std::string Root::catalogVersion() const
+std::string Root::applicationVersion() const
{
return d->version;
}
SG_LOG(SG_GENERAL, SG_ALERT, "failed to install package:"
<< 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);
+ d->fireFinishInstall(aInstall, aReason);
}
-
+
void Root::cancelDownload(InstallRef aInstall)
{
RootPrivate::UpdateDeque::iterator it =
// this will add to our cache, and hence, modify m_installs
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();
}
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.
*/
- std::string catalogVersion() const;
-
+ std::string applicationVersion() const;
+
/**
* refresh catalogs which are more than the maximum age (24 hours by default)
* set force to true, to download all catalogs regardless of age.