X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fpackage%2FCatalog.cxx;h=c9c6565836ae0a4d970fb8c76671e8477fbef496;hb=a3f1bb546fec72b07f11f69934e6894696fea57a;hp=c12a53a0dee94be84c99535933e97bb320c5cd74;hpb=b7fbb7956535ea89cdf6f9d1a77fc8799efd93b0;p=simgear.git diff --git a/simgear/package/Catalog.cxx b/simgear/package/Catalog.cxx index c12a53a0..c9c65658 100644 --- a/simgear/package/Catalog.cxx +++ b/simgear/package/Catalog.cxx @@ -31,6 +31,7 @@ #include #include #include +#include namespace simgear { @@ -40,18 +41,32 @@ bool checkVersion(const std::string& aVersion, SGPropertyNode_ptr props) { BOOST_FOREACH(SGPropertyNode* v, props->getChildren("version")) { std::string s(v->getStringValue()); - if (s== aVersion) { + if (s == aVersion) { return true; } - // allow 3.5.* to match any of 3.5.0, 3.5.1rc1, 3.5.11 or so on - if (strutils::ends_with(s, ".*")) { - size_t lastDot = aVersion.rfind('.'); - std::string ver = aVersion.substr(0, lastDot); - if (ver == s.substr(0, s.length() - 2)) { - return true; + // examine each dot-seperated component in turn, supporting a wildcard + // in the versions from the catalog. + string_list appVersionParts = simgear::strutils::split(aVersion, "."); + string_list catVersionParts = simgear::strutils::split(s, "."); + + size_t partCount = appVersionParts.size(); + if (partCount != catVersionParts.size()) { + continue; + } + + bool ok = true; + for (unsigned int p=0; p < partCount; ++p) { + if (catVersionParts[p] == "*") { + // always passes + } else if (appVersionParts[p] != catVersionParts[p]) { + ok = false; } } + + if (ok) { + return true; + } } return false; } @@ -63,7 +78,7 @@ std::string redirectUrlForVersion(const std::string& aVersion, SGPropertyNode_pt return v->getStringValue("url"); } } - + return std::string(); } @@ -77,8 +92,7 @@ public: m_owner(aOwner) { // refreshing - m_owner->changeStatus(Delegate::FAIL_IN_PROGRESS); - + m_owner->changeStatus(Delegate::STATUS_IN_PROGRESS); } protected: @@ -90,8 +104,13 @@ protected: 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; } @@ -106,7 +125,15 @@ protected: 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); @@ -138,7 +165,7 @@ protected: time(&m_owner->m_retrievedTime); m_owner->writeTimestamp(); - m_owner->refreshComplete(Delegate::CATALOG_REFRESHED); + m_owner->refreshComplete(Delegate::STATUS_REFRESHED); } private: @@ -164,9 +191,7 @@ CatalogRef Catalog::createFromUrl(Root* aRoot, const std::string& aUrl) { CatalogRef c = new Catalog(aRoot); c->m_url = aUrl; - Downloader* dl = new Downloader(c, aUrl); - aRoot->makeHTTPRequest(dl); - + c->refresh(); return c; } @@ -186,27 +211,27 @@ CatalogRef Catalog::createFromPath(Root* aRoot, const SGPath& aPath) return NULL; } - if (!checkVersion(aRoot->catalogVersion(), props)) { - std::string redirect = redirectUrlForVersion(aRoot->catalogVersion(), props); - if (!redirect.empty()) { - SG_LOG(SG_GENERAL, SG_WARN, "catalog at " << aPath << ", version mismatch:\n\t" - << "redirecting to alternate URL:" << redirect); - CatalogRef c = Catalog::createFromUrl(aRoot, redirect); - c->m_installRoot = aPath; - return c; - } else { - SG_LOG(SG_GENERAL, SG_WARN, "skipping catalog at " << aPath << ", version mismatch:\n\t" - << props->getStringValue("version") << " vs required " << aRoot->catalogVersion()); - return NULL; - } + bool versionCheckOk = checkVersion(aRoot->applicationVersion(), props); + if (!versionCheckOk) { + SG_LOG(SG_GENERAL, SG_INFO, "catalog at:" << aPath << " failed version check: need" << aRoot->applicationVersion()); + // keep the catalog but mark it as needing an update + } else { + SG_LOG(SG_GENERAL, SG_DEBUG, "creating catalog from:" << aPath); } CatalogRef c = new Catalog(aRoot); c->m_installRoot = aPath; - c->parseProps(props); // will set status + c->parseProps(props); c->parseTimestamp(); + if (versionCheckOk) { + // parsed XML ok, mark status as valid + c->changeStatus(Delegate::STATUS_SUCCESS); + } else { + c->changeStatus(Delegate::FAIL_VERSION); + } + return c; } @@ -214,7 +239,7 @@ bool Catalog::uninstall() { bool ok; bool atLeastOneFailure = false; - + BOOST_FOREACH(PackageRef p, installedPackages()) { ok = p->existingInstall()->uninstall(); if (!ok) { @@ -231,9 +256,9 @@ bool Catalog::uninstall() if (!ok) { atLeastOneFailure = true; } - + changeStatus(atLeastOneFailure ? Delegate::FAIL_FILESYSTEM - : Delegate::FAIL_SUCCESS); + : Delegate::STATUS_SUCCESS); return ok; } @@ -283,31 +308,31 @@ Catalog::installedPackages() const return r; } -InstallRef Catalog::installForPackage(PackageRef pkg) const +void Catalog::refresh() { - PackageInstallDict::const_iterator it = m_installed.find(pkg); - if (it == m_installed.end()) { - // check if it exists on disk, create - - SGPath p(pkg->pathOnDisk()); - if (p.exists()) { - return Install::createFromPath(p, CatalogRef(const_cast(this))); - } - - return NULL; + if (m_refreshRequest.valid()) { + // refresh in progress + return; } - return it->second; -} - -void Catalog::refresh() -{ Downloader* dl = new Downloader(this, url()); - // will iupdate status to IN_PROGRESS + m_refreshRequest = dl; + // will update status to IN_PROGRESS m_root->makeHTTPRequest(dl); - m_root->catalogRefreshBegin(this); } +struct FindById +{ + FindById(const std::string &id) : m_id(id) {} + + bool operator()(const PackageRef& ref) const + { + return ref->id() == m_id; + } + + std::string m_id; +}; + void Catalog::parseProps(const SGPropertyNode* aProps) { // copy everything except package children? @@ -321,8 +346,14 @@ void Catalog::parseProps(const SGPropertyNode* aProps) for (int i = 0; i < nChildren; i++) { const SGPropertyNode* pkgProps = aProps->getChild(i); if (strcmp(pkgProps->getName(), "package") == 0) { - PackageRef p = getPackageById(pkgProps->getStringValue("id")); - if (p) { + // can't use getPackageById here becuase the variant dict isn't + // built yet. Instead we need to look at m_packages directly. + + PackageList::iterator pit = std::find_if(m_packages.begin(), m_packages.end(), + FindById(pkgProps->getStringValue("id"))); + PackageRef p; + if (pit != m_packages.end()) { + p = *pit; // existing package p->updateFromProps(pkgProps); orphans.erase(p); // not an orphan @@ -372,9 +403,6 @@ void Catalog::parseProps(const SGPropertyNode* aProps) Dir d(m_installRoot); d.create(0755); } - - // parsed XML ok, mark status as valid - changeStatus(Delegate::FAIL_SUCCESS); } PackageRef Catalog::getPackageById(const std::string& aId) const @@ -383,11 +411,23 @@ PackageRef Catalog::getPackageById(const std::string& aId) const // 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"); @@ -398,6 +438,11 @@ std::string Catalog::url() const return m_url; } +std::string Catalog::name() const +{ + return getLocalisedString(m_props, "name"); +} + std::string Catalog::description() const { return getLocalisedString(m_props, "description"); @@ -434,12 +479,21 @@ unsigned int Catalog::ageInSeconds() const bool Catalog::needsRefresh() const { + // always refresh in these cases + if ((m_status == Delegate::FAIL_VERSION) || (m_status == Delegate::FAIL_DOWNLOAD)) { + return true; + } + unsigned int maxAge = m_props->getIntValue("max-age-sec", m_root->maxAgeSeconds()); return (ageInSeconds() > maxAge); } std::string Catalog::getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const { + if (!aRoot) { + return std::string(); + } + if (aRoot->hasChild(m_root->getLocale())) { const SGPropertyNode* localeRoot = aRoot->getChild(m_root->getLocale().c_str()); if (localeRoot->hasChild(aName)) { @@ -450,37 +504,20 @@ std::string Catalog::getLocalisedString(const SGPropertyNode* aRoot, const char* return aRoot->getStringValue(aName); } -void Catalog::refreshComplete(Delegate::FailureCode aReason) +void Catalog::refreshComplete(Delegate::StatusCode aReason) { - m_root->catalogRefreshComplete(this, aReason); changeStatus(aReason); + m_refreshRequest.reset(); } -void Catalog::registerInstall(Install* ins) -{ - if (!ins || ins->package()->catalog() != this) { - return; - } - - m_installed[ins->package()] = ins; -} - -void Catalog::unregisterInstall(Install* ins) -{ - if (!ins || ins->package()->catalog() != this) { - return; - } - - m_installed.erase(ins->package()); -} - -void Catalog::changeStatus(Delegate::FailureCode newStatus) +void Catalog::changeStatus(Delegate::StatusCode newStatus) { if (m_status == newStatus) { return; } - + m_status = newStatus; + m_root->catalogRefreshStatus(this, newStatus); m_statusCallbacks(this); } @@ -489,7 +526,7 @@ void Catalog::addStatusCallback(const Callback& cb) m_statusCallbacks.push_back(cb); } -Delegate::FailureCode Catalog::status() const +Delegate::StatusCode Catalog::status() const { return m_status; }