Packages: better version handling & migration
Add test coverage for disabling a catalog due to version, and also for auto-migrating to a new version. Expose disabled catalogs on the Root, so they can be checked for.
This commit is contained in:
@@ -84,7 +84,7 @@ bool checkVersion(const std::string& aVersion, SGPropertyNode_ptr props)
|
|||||||
|
|
||||||
std::string redirectUrlForVersion(const std::string& aVersion, SGPropertyNode_ptr props)
|
std::string redirectUrlForVersion(const std::string& aVersion, SGPropertyNode_ptr props)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(SGPropertyNode* v, props->getChildren("alternate-version")) {
|
for (SGPropertyNode* v : props->getChildren("alternate-version")) {
|
||||||
std::string s(v->getStringValue("version"));
|
std::string s(v->getStringValue("version"));
|
||||||
if (checkVersionString(aVersion, s)) {
|
if (checkVersionString(aVersion, s)) {
|
||||||
return v->getStringValue("url");;
|
return v->getStringValue("url");;
|
||||||
@@ -139,7 +139,7 @@ protected:
|
|||||||
|
|
||||||
std::string ver(m_owner->root()->applicationVersion());
|
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 required " << ver);
|
SG_LOG(SG_GENERAL, SG_WARN, "downloaded catalog " << m_owner->url() << ", but version required " << ver);
|
||||||
|
|
||||||
// check for a version redirect entry
|
// check for a version redirect entry
|
||||||
std::string url = redirectUrlForVersion(ver, props);
|
std::string url = redirectUrlForVersion(ver, props);
|
||||||
@@ -170,6 +170,12 @@ protected:
|
|||||||
m_owner->refreshComplete(Delegate::STATUS_REFRESHED);
|
m_owner->refreshComplete(Delegate::STATUS_REFRESHED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onFail() override
|
||||||
|
{
|
||||||
|
// network level failure
|
||||||
|
SG_LOG(SG_GENERAL, SG_WARN, "catalog network failure for:" << m_owner->url());
|
||||||
|
m_owner->refreshComplete(Delegate::FAIL_DOWNLOAD);
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
|
|
||||||
CatalogRef m_owner;
|
CatalogRef m_owner;
|
||||||
@@ -215,7 +221,8 @@ CatalogRef Catalog::createFromPath(Root* aRoot, const SGPath& aPath)
|
|||||||
|
|
||||||
bool versionCheckOk = checkVersion(aRoot->applicationVersion(), props);
|
bool versionCheckOk = checkVersion(aRoot->applicationVersion(), props);
|
||||||
if (!versionCheckOk) {
|
if (!versionCheckOk) {
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "catalog at:" << aPath << " failed version check: need" << aRoot->applicationVersion());
|
SG_LOG(SG_GENERAL, SG_INFO, "catalog at:" << aPath << " failed version check: need version: "
|
||||||
|
<< aRoot->applicationVersion());
|
||||||
// keep the catalog but mark it as needing an update
|
// keep the catalog but mark it as needing an update
|
||||||
} else {
|
} else {
|
||||||
SG_LOG(SG_GENERAL, SG_DEBUG, "creating catalog from:" << aPath);
|
SG_LOG(SG_GENERAL, SG_DEBUG, "creating catalog from:" << aPath);
|
||||||
@@ -540,6 +547,20 @@ Delegate::StatusCode Catalog::status() const
|
|||||||
return m_status;
|
return m_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Catalog::isEnabled() const
|
||||||
|
{
|
||||||
|
switch (m_status) {
|
||||||
|
case Delegate::STATUS_SUCCESS:
|
||||||
|
case Delegate::STATUS_REFRESHED:
|
||||||
|
case Delegate::STATUS_IN_PROGRESS:
|
||||||
|
// this is important so we can use Catalog aircraft in offline mode
|
||||||
|
case Delegate::FAIL_DOWNLOAD:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // of namespace pkg
|
} // of namespace pkg
|
||||||
|
|
||||||
} // of namespace simgear
|
} // of namespace simgear
|
||||||
|
|||||||
@@ -135,6 +135,12 @@ public:
|
|||||||
|
|
||||||
Delegate::StatusCode status() const;
|
Delegate::StatusCode status() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* is this Catalog usable? This may be false if the catalog is currently
|
||||||
|
* failing a version check or cannot be updated
|
||||||
|
*/
|
||||||
|
bool isEnabled() const;
|
||||||
|
|
||||||
typedef boost::function<void(Catalog*)> Callback;
|
typedef boost::function<void(Catalog*)> Callback;
|
||||||
|
|
||||||
void addStatusCallback(const Callback& cb);
|
void addStatusCallback(const Callback& cb);
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ std::string readFileIntoString(const SGPath& path)
|
|||||||
|
|
||||||
SGPath global_serverFilesRoot;
|
SGPath global_serverFilesRoot;
|
||||||
unsigned int global_catalogVersion = 0;
|
unsigned int global_catalogVersion = 0;
|
||||||
|
bool global_failRequests = false;
|
||||||
|
|
||||||
class TestPackageChannel : public TestServerChannel
|
class TestPackageChannel : public TestServerChannel
|
||||||
{
|
{
|
||||||
@@ -71,6 +72,10 @@ public:
|
|||||||
state = STATE_IDLE;
|
state = STATE_IDLE;
|
||||||
SGPath localPath(global_serverFilesRoot);
|
SGPath localPath(global_serverFilesRoot);
|
||||||
|
|
||||||
|
if (global_failRequests) {
|
||||||
|
closeWhenDone();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (path == "/catalogTest1/catalog.xml") {
|
if (path == "/catalogTest1/catalog.xml") {
|
||||||
if (global_catalogVersion > 0) {
|
if (global_catalogVersion > 0) {
|
||||||
@@ -540,6 +545,186 @@ void testInstallTarPackage(HTTP::Client* cl)
|
|||||||
SG_VERIFY(p.exists());
|
SG_VERIFY(p.exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testDisableDueToVersion(HTTP::Client* cl)
|
||||||
|
{
|
||||||
|
global_catalogVersion = 0;
|
||||||
|
SGPath rootPath(simgear::Dir::current().path());
|
||||||
|
rootPath.append("cat_disable_at_version");
|
||||||
|
simgear::Dir pd(rootPath);
|
||||||
|
pd.removeChildren();
|
||||||
|
|
||||||
|
{
|
||||||
|
pkg::RootRef root(new pkg::Root(rootPath, "8.1.2"));
|
||||||
|
root->setHTTPClient(cl);
|
||||||
|
|
||||||
|
pkg::CatalogRef c = pkg::Catalog::createFromUrl(root.ptr(), "http://localhost:2000/catalogTest1/catalog.xml");
|
||||||
|
waitForUpdateComplete(cl, root);
|
||||||
|
SG_VERIFY(c->isEnabled());
|
||||||
|
|
||||||
|
// install a package
|
||||||
|
pkg::PackageRef p1 = root->getPackageById("org.flightgear.test.catalog1.b737-NG");
|
||||||
|
SG_CHECK_EQUAL(p1->id(), "b737-NG");
|
||||||
|
pkg::InstallRef ins = p1->install();
|
||||||
|
SG_VERIFY(ins->isQueued());
|
||||||
|
waitForUpdateComplete(cl, root);
|
||||||
|
SG_VERIFY(p1->isInstalled());
|
||||||
|
}
|
||||||
|
|
||||||
|
// bump version and refresh
|
||||||
|
{
|
||||||
|
pkg::RootRef root(new pkg::Root(rootPath, "9.1.2"));
|
||||||
|
pkg::CatalogRef cat = root->getCatalogById("org.flightgear.test.catalog1");
|
||||||
|
SG_CHECK_EQUAL(root->allCatalogs().size(), 1);
|
||||||
|
SG_VERIFY(!cat->isEnabled());
|
||||||
|
SG_CHECK_EQUAL(root->catalogs().size(), 0);
|
||||||
|
|
||||||
|
root->setHTTPClient(cl);
|
||||||
|
root->refresh();
|
||||||
|
waitForUpdateComplete(cl, root);
|
||||||
|
SG_CHECK_EQUAL(root->allCatalogs().size(), 1);
|
||||||
|
|
||||||
|
|
||||||
|
SG_CHECK_EQUAL(cat->status(), pkg::Delegate::FAIL_VERSION);
|
||||||
|
SG_VERIFY(!cat->isEnabled());
|
||||||
|
SG_CHECK_EQUAL(cat->id(), "org.flightgear.test.catalog1");
|
||||||
|
|
||||||
|
auto enabledCats = root->catalogs();
|
||||||
|
auto it = std::find(enabledCats.begin(), enabledCats.end(), cat);
|
||||||
|
SG_VERIFY(it == enabledCats.end());
|
||||||
|
SG_CHECK_EQUAL(enabledCats.size(), 0);
|
||||||
|
|
||||||
|
auto allCats = root->allCatalogs();
|
||||||
|
auto j = std::find(allCats.begin(), allCats.end(), cat);
|
||||||
|
SG_VERIFY(j != allCats.end());
|
||||||
|
|
||||||
|
SG_CHECK_EQUAL(allCats.size(), 1);
|
||||||
|
|
||||||
|
// ensure existing package is still installed but not directly list
|
||||||
|
|
||||||
|
pkg::PackageRef p1 = root->getPackageById("org.flightgear.test.catalog1.b737-NG");
|
||||||
|
SG_VERIFY(p1 != pkg::PackageRef());
|
||||||
|
SG_CHECK_EQUAL(p1->id(), "b737-NG");
|
||||||
|
|
||||||
|
auto packs = root->allPackages();
|
||||||
|
auto k = std::find(packs.begin(), packs.end(), p1);
|
||||||
|
SG_VERIFY(k == packs.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void testVersionMigrate(HTTP::Client* cl)
|
||||||
|
{
|
||||||
|
global_catalogVersion = 2; // version which has migration info
|
||||||
|
SGPath rootPath(simgear::Dir::current().path());
|
||||||
|
rootPath.append("cat_migrate_version");
|
||||||
|
simgear::Dir pd(rootPath);
|
||||||
|
pd.removeChildren();
|
||||||
|
|
||||||
|
{
|
||||||
|
pkg::RootRef root(new pkg::Root(rootPath, "8.1.2"));
|
||||||
|
root->setHTTPClient(cl);
|
||||||
|
|
||||||
|
pkg::CatalogRef c = pkg::Catalog::createFromUrl(root.ptr(), "http://localhost:2000/catalogTest1/catalog.xml");
|
||||||
|
waitForUpdateComplete(cl, root);
|
||||||
|
SG_VERIFY(c->isEnabled());
|
||||||
|
|
||||||
|
// install a package
|
||||||
|
pkg::PackageRef p1 = root->getPackageById("org.flightgear.test.catalog1.b737-NG");
|
||||||
|
SG_CHECK_EQUAL(p1->id(), "b737-NG");
|
||||||
|
pkg::InstallRef ins = p1->install();
|
||||||
|
SG_VERIFY(ins->isQueued());
|
||||||
|
waitForUpdateComplete(cl, root);
|
||||||
|
SG_VERIFY(p1->isInstalled());
|
||||||
|
}
|
||||||
|
|
||||||
|
// bump version and refresh
|
||||||
|
{
|
||||||
|
pkg::RootRef root(new pkg::Root(rootPath, "10.1.2"));
|
||||||
|
root->setHTTPClient(cl);
|
||||||
|
|
||||||
|
// this should cause auto-migration
|
||||||
|
root->refresh(true);
|
||||||
|
waitForUpdateComplete(cl, root);
|
||||||
|
|
||||||
|
pkg::CatalogRef cat = root->getCatalogById("org.flightgear.test.catalog1");
|
||||||
|
SG_VERIFY(cat->isEnabled());
|
||||||
|
SG_CHECK_EQUAL(cat->status(), pkg::Delegate::STATUS_REFRESHED);
|
||||||
|
SG_CHECK_EQUAL(cat->id(), "org.flightgear.test.catalog1");
|
||||||
|
SG_CHECK_EQUAL(cat->url(), "http://localhost:2000/catalogTest1/catalog-v10.xml");
|
||||||
|
|
||||||
|
auto enabledCats = root->catalogs();
|
||||||
|
auto it = std::find(enabledCats.begin(), enabledCats.end(), cat);
|
||||||
|
SG_VERIFY(it != enabledCats.end());
|
||||||
|
|
||||||
|
// ensure existing package is still installed
|
||||||
|
|
||||||
|
pkg::PackageRef p1 = root->getPackageById("org.flightgear.test.catalog1.b737-NG");
|
||||||
|
SG_VERIFY(p1 != pkg::PackageRef());
|
||||||
|
SG_CHECK_EQUAL(p1->id(), "b737-NG");
|
||||||
|
|
||||||
|
auto packs = root->allPackages();
|
||||||
|
auto k = std::find(packs.begin(), packs.end(), p1);
|
||||||
|
SG_VERIFY(k != packs.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void testOfflineMode(HTTP::Client* cl)
|
||||||
|
{
|
||||||
|
global_catalogVersion = 0;
|
||||||
|
SGPath rootPath(simgear::Dir::current().path());
|
||||||
|
rootPath.append("cat_offline_mode");
|
||||||
|
simgear::Dir pd(rootPath);
|
||||||
|
pd.removeChildren();
|
||||||
|
|
||||||
|
{
|
||||||
|
pkg::RootRef root(new pkg::Root(rootPath, "8.1.2"));
|
||||||
|
root->setHTTPClient(cl);
|
||||||
|
|
||||||
|
pkg::CatalogRef c = pkg::Catalog::createFromUrl(root.ptr(), "http://localhost:2000/catalogTest1/catalog.xml");
|
||||||
|
waitForUpdateComplete(cl, root);
|
||||||
|
SG_VERIFY(c->isEnabled());
|
||||||
|
|
||||||
|
// install a package
|
||||||
|
pkg::PackageRef p1 = root->getPackageById("org.flightgear.test.catalog1.b737-NG");
|
||||||
|
SG_CHECK_EQUAL(p1->id(), "b737-NG");
|
||||||
|
pkg::InstallRef ins = p1->install();
|
||||||
|
SG_VERIFY(ins->isQueued());
|
||||||
|
waitForUpdateComplete(cl, root);
|
||||||
|
SG_VERIFY(p1->isInstalled());
|
||||||
|
}
|
||||||
|
|
||||||
|
global_failRequests = true;
|
||||||
|
|
||||||
|
{
|
||||||
|
pkg::RootRef root(new pkg::Root(rootPath, "8.1.2"));
|
||||||
|
SG_CHECK_EQUAL(root->catalogs().size(), 1);
|
||||||
|
|
||||||
|
root->setHTTPClient(cl);
|
||||||
|
root->refresh(true);
|
||||||
|
waitForUpdateComplete(cl, root);
|
||||||
|
SG_CHECK_EQUAL(root->catalogs().size(), 1);
|
||||||
|
|
||||||
|
pkg::CatalogRef cat = root->getCatalogById("org.flightgear.test.catalog1");
|
||||||
|
SG_VERIFY(cat->isEnabled());
|
||||||
|
SG_CHECK_EQUAL(cat->status(), pkg::Delegate::FAIL_DOWNLOAD);
|
||||||
|
SG_CHECK_EQUAL(cat->id(), "org.flightgear.test.catalog1");
|
||||||
|
|
||||||
|
auto enabledCats = root->catalogs();
|
||||||
|
auto it = std::find(enabledCats.begin(), enabledCats.end(), cat);
|
||||||
|
SG_VERIFY(it != enabledCats.end());
|
||||||
|
|
||||||
|
// ensure existing package is still installed
|
||||||
|
pkg::PackageRef p1 = root->getPackageById("org.flightgear.test.catalog1.b737-NG");
|
||||||
|
SG_VERIFY(p1 != pkg::PackageRef());
|
||||||
|
SG_CHECK_EQUAL(p1->id(), "b737-NG");
|
||||||
|
|
||||||
|
auto packs = root->allPackages();
|
||||||
|
auto k = std::find(packs.begin(), packs.end(), p1);
|
||||||
|
SG_VERIFY(k != packs.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
global_failRequests = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
@@ -564,6 +749,12 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
testInstallTarPackage(&cl);
|
testInstallTarPackage(&cl);
|
||||||
|
|
||||||
|
testDisableDueToVersion(&cl);
|
||||||
|
|
||||||
|
testOfflineMode(&cl);
|
||||||
|
|
||||||
|
testVersionMigrate(&cl);
|
||||||
|
|
||||||
std::cout << "Successfully passed all tests!" << std::endl;
|
std::cout << "Successfully passed all tests!" << std::endl;
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
+33
-35
@@ -408,15 +408,11 @@ Root::Root(const SGPath& aPath, const std::string& aVersion) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (SGPath c : dir.children(Dir::TYPE_DIR | Dir::NO_DOT_OR_DOTDOT)) {
|
for (SGPath c : dir.children(Dir::TYPE_DIR | Dir::NO_DOT_OR_DOTDOT)) {
|
||||||
CatalogRef cat = Catalog::createFromPath(this, c);
|
// note this will set the catalog status, which will insert into
|
||||||
if (cat) {
|
// disabled catalogs automatically if necesary
|
||||||
if (cat->status() == Delegate::STATUS_SUCCESS) {
|
auto cat = Catalog::createFromPath(this, c);
|
||||||
d->catalogs[cat->id()] = cat;
|
if (cat && cat->isEnabled()) {
|
||||||
} else {
|
d->catalogs.insert({cat->id(), cat});
|
||||||
// catalog has problems, such as needing an update
|
|
||||||
// keep it out of the main collection for now
|
|
||||||
d->disabledCatalogs.push_back(cat);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // of child directories iteration
|
} // of child directories iteration
|
||||||
}
|
}
|
||||||
@@ -438,9 +434,15 @@ std::string Root::applicationVersion() const
|
|||||||
|
|
||||||
CatalogRef Root::getCatalogById(const std::string& aId) const
|
CatalogRef Root::getCatalogById(const std::string& aId) const
|
||||||
{
|
{
|
||||||
CatalogDict::const_iterator it = d->catalogs.find(aId);
|
auto it = d->catalogs.find(aId);
|
||||||
if (it == d->catalogs.end()) {
|
if (it == d->catalogs.end()) {
|
||||||
return NULL;
|
// check disabled catalog list
|
||||||
|
auto j = std::find_if(d->disabledCatalogs.begin(), d->disabledCatalogs.end(),
|
||||||
|
[aId](const CatalogRef& cat) { return cat->id() == aId; });
|
||||||
|
if (j != d->disabledCatalogs.end()) {
|
||||||
|
return *j;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return it->second;
|
return it->second;
|
||||||
@@ -485,6 +487,13 @@ CatalogList Root::catalogs() const
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CatalogList Root::allCatalogs() const
|
||||||
|
{
|
||||||
|
CatalogList r = catalogs();
|
||||||
|
r.insert(r.end(), d->disabledCatalogs.begin(), d->disabledCatalogs.end());
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
PackageList
|
PackageList
|
||||||
Root::allPackages() const
|
Root::allPackages() const
|
||||||
{
|
{
|
||||||
@@ -544,12 +553,9 @@ void Root::refresh(bool aForce)
|
|||||||
|
|
||||||
toRefresh.insert(toRefresh.end(), d->disabledCatalogs.begin(),
|
toRefresh.insert(toRefresh.end(), d->disabledCatalogs.begin(),
|
||||||
d->disabledCatalogs.end());
|
d->disabledCatalogs.end());
|
||||||
|
for (auto cat : toRefresh) {
|
||||||
|
cat->refresh();
|
||||||
CatalogList::iterator j = toRefresh.begin();
|
didStartAny = true;
|
||||||
for (; j != toRefresh.end(); ++j) {
|
|
||||||
(*j)->refresh();
|
|
||||||
didStartAny = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!didStartAny) {
|
if (!didStartAny) {
|
||||||
@@ -677,23 +683,20 @@ void Root::catalogRefreshStatus(CatalogRef aCat, Delegate::StatusCode aReason)
|
|||||||
d->catalogs.insert(catIt, CatalogDict::value_type(aCat->id(), aCat));
|
d->catalogs.insert(catIt, CatalogDict::value_type(aCat->id(), aCat));
|
||||||
|
|
||||||
// catalog might have been previously disabled, let's remove in that case
|
// catalog might have been previously disabled, let's remove in that case
|
||||||
CatalogList::iterator j = std::find(d->disabledCatalogs.begin(),
|
auto j = std::find(d->disabledCatalogs.begin(),
|
||||||
d->disabledCatalogs.end(),
|
d->disabledCatalogs.end(),
|
||||||
aCat);
|
aCat);
|
||||||
if (j != d->disabledCatalogs.end()) {
|
if (j != d->disabledCatalogs.end()) {
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "re-enabling disabled catalog:" << aCat->id());
|
SG_LOG(SG_GENERAL, SG_INFO, "re-enabling disabled catalog:" << aCat->id());
|
||||||
d->disabledCatalogs.erase(j);
|
d->disabledCatalogs.erase(j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((aReason != Delegate::STATUS_REFRESHED) &&
|
if (!aCat->isEnabled()) {
|
||||||
(aReason != Delegate::STATUS_IN_PROGRESS) &&
|
|
||||||
(aReason != Delegate::STATUS_SUCCESS))
|
|
||||||
{
|
|
||||||
// catalog has errors, disable it
|
// catalog has errors, disable it
|
||||||
CatalogList::iterator j = std::find(d->disabledCatalogs.begin(),
|
auto j = std::find(d->disabledCatalogs.begin(),
|
||||||
d->disabledCatalogs.end(),
|
d->disabledCatalogs.end(),
|
||||||
aCat);
|
aCat);
|
||||||
if (j == d->disabledCatalogs.end()) {
|
if (j == d->disabledCatalogs.end()) {
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "disabling catalog:" << aCat->id());
|
SG_LOG(SG_GENERAL, SG_INFO, "disabling catalog:" << aCat->id());
|
||||||
d->disabledCatalogs.push_back(aCat);
|
d->disabledCatalogs.push_back(aCat);
|
||||||
@@ -703,7 +706,7 @@ void Root::catalogRefreshStatus(CatalogRef aCat, Delegate::StatusCode aReason)
|
|||||||
if (catIt != d->catalogs.end()) {
|
if (catIt != d->catalogs.end()) {
|
||||||
d->catalogs.erase(catIt);
|
d->catalogs.erase(catIt);
|
||||||
}
|
}
|
||||||
} // of catalog has errors case
|
} // of catalog is disabled
|
||||||
|
|
||||||
if (d->refreshing.empty()) {
|
if (d->refreshing.empty()) {
|
||||||
d->fireRefreshStatus(CatalogRef(), Delegate::STATUS_REFRESHED);
|
d->fireRefreshStatus(CatalogRef(), Delegate::STATUS_REFRESHED);
|
||||||
@@ -718,13 +721,8 @@ bool Root::removeCatalogById(const std::string& aId)
|
|||||||
CatalogDict::iterator catIt = d->catalogs.find(aId);
|
CatalogDict::iterator catIt = d->catalogs.find(aId);
|
||||||
if (catIt == d->catalogs.end()) {
|
if (catIt == d->catalogs.end()) {
|
||||||
// check the disabled list
|
// check the disabled list
|
||||||
CatalogList::iterator j = d->disabledCatalogs.begin();
|
auto j = std::find_if(d->disabledCatalogs.begin(), d->disabledCatalogs.end(),
|
||||||
for (; j != d->disabledCatalogs.end(); ++j) {
|
[aId](const CatalogRef& cat) { return cat->id() == aId; });
|
||||||
if ((*j)->id() == aId) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j == d->disabledCatalogs.end()) {
|
if (j == d->disabledCatalogs.end()) {
|
||||||
SG_LOG(SG_GENERAL, SG_WARN, "removeCatalogById: no catalog with id:" << aId);
|
SG_LOG(SG_GENERAL, SG_WARN, "removeCatalogById: no catalog with id:" << aId);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -70,6 +70,12 @@ public:
|
|||||||
|
|
||||||
CatalogList catalogs() const;
|
CatalogList catalogs() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retrive all catalogs, including currently disabled ones
|
||||||
|
*/
|
||||||
|
CatalogList allCatalogs() const;
|
||||||
|
|
||||||
|
|
||||||
void setMaxAgeSeconds(unsigned int seconds);
|
void setMaxAgeSeconds(unsigned int seconds);
|
||||||
unsigned int maxAgeSeconds() const;
|
unsigned int maxAgeSeconds() const;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,178 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<PropertyList>
|
||||||
|
<id>org.flightgear.test.catalog1</id>
|
||||||
|
<description>First test catalog</description>
|
||||||
|
<url>http://localhost:2000/catalogTest1/catalog-v10.xml</url>
|
||||||
|
<catalog-version>4</catalog-version>
|
||||||
|
|
||||||
|
<version>10.0.*</version>
|
||||||
|
<version>10.1.*</version>
|
||||||
|
<package>
|
||||||
|
<id>alpha</id>
|
||||||
|
<name>Alpha package</name>
|
||||||
|
<revision type="int">8</revision>
|
||||||
|
<file-size-bytes type="int">593</file-size-bytes>
|
||||||
|
|
||||||
|
<md5>a469c4b837f0521db48616cfe65ac1ea</md5>
|
||||||
|
<url>http://localhost:2000/catalogTest1/alpha.zip</url>
|
||||||
|
|
||||||
|
<dir>alpha</dir>
|
||||||
|
|
||||||
|
</package>
|
||||||
|
|
||||||
|
<package>
|
||||||
|
<id>c172p</id>
|
||||||
|
<name>Cessna 172-P</name>
|
||||||
|
<dir>c172p</dir>
|
||||||
|
<description>A plane made by Cessna on Jupiter</description>
|
||||||
|
<revision type="int">42</revision>
|
||||||
|
<file-size-bytes type="int">860</file-size-bytes>
|
||||||
|
<author>Standard author</author>
|
||||||
|
|
||||||
|
<tag>cessna</tag>
|
||||||
|
<tag>ga</tag>
|
||||||
|
<tag>piston</tag>
|
||||||
|
<tag>ifr</tag>
|
||||||
|
|
||||||
|
<rating>
|
||||||
|
<FDM type="int">3</FDM>
|
||||||
|
<systems type="int">4</systems>
|
||||||
|
<model type="int">5</model>
|
||||||
|
<cockpit type="int">4</cockpit>
|
||||||
|
</rating>
|
||||||
|
|
||||||
|
<!-- local dependency -->
|
||||||
|
<depends>
|
||||||
|
<id>org.flightgear.test.catalog1.common-sounds</id>
|
||||||
|
<revision>10</revision>
|
||||||
|
</depends>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>exterior</type>
|
||||||
|
<path>thumb-exterior.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-exterior.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>panel</type>
|
||||||
|
<path>thumb-panel.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-panel.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<path>thumb-something.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-something.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<variant>
|
||||||
|
<id>c172p-2d-panel</id>
|
||||||
|
<name>C172 with 2d panel only</name>
|
||||||
|
</variant>
|
||||||
|
|
||||||
|
<variant>
|
||||||
|
<id>c172p-floats</id>
|
||||||
|
<name>C172 with floats</name>
|
||||||
|
<description>A plane with floats</description>
|
||||||
|
<author>Floats variant author</author>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>exterior</type>
|
||||||
|
<path>thumb-exterior-floats.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-exterior-floats.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>panel</type>
|
||||||
|
<path>thumb-panel.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-panel.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<thumbnail>http://foo.bar.com/thumb-floats.png</thumbnail>
|
||||||
|
<thumbnail-path>thumb-floats.png</thumbnail-path>
|
||||||
|
</variant>
|
||||||
|
|
||||||
|
<variant>
|
||||||
|
<id>c172p-skis</id>
|
||||||
|
<name>C172 with skis</name>
|
||||||
|
<description>A plane with skis</description>
|
||||||
|
|
||||||
|
<variant-of>c172p</variant-of>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>exterior</type>
|
||||||
|
<path>thumb-exterior-skis.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-exterior-skis.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>panel</type>
|
||||||
|
<path>thumb-panel.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-panel.png</url>
|
||||||
|
</preview>
|
||||||
|
</variant>
|
||||||
|
|
||||||
|
<variant>
|
||||||
|
<id>c172r</id>
|
||||||
|
<name>C172R</name>
|
||||||
|
<description>Equally good version of the C172</description>
|
||||||
|
<variant-of>_package_</variant-of>
|
||||||
|
<preview>
|
||||||
|
<type>panel</type>
|
||||||
|
<path>thumb-panel.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-panel.png</url>
|
||||||
|
</preview>
|
||||||
|
</variant>
|
||||||
|
|
||||||
|
<variant>
|
||||||
|
<id>c172r-floats</id>
|
||||||
|
<name>C172R-floats</name>
|
||||||
|
<description>Equally good version of the C172 with floats</description>
|
||||||
|
<variant-of>c172r</variant-of>
|
||||||
|
<preview>
|
||||||
|
<type>panel</type>
|
||||||
|
<path>thumb-panel.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-panel.png</url>
|
||||||
|
</preview>
|
||||||
|
</variant>
|
||||||
|
|
||||||
|
<md5>ec0e2ffdf98d6a5c05c77445e5447ff5</md5>
|
||||||
|
<url>http://localhost:2000/catalogTest1/c172p.zip</url>
|
||||||
|
|
||||||
|
<thumbnail>http://foo.bar.com/thumb-exterior.png</thumbnail>
|
||||||
|
<thumbnail-path>exterior.png</thumbnail-path>
|
||||||
|
</package>
|
||||||
|
|
||||||
|
<package>
|
||||||
|
<id>b737-NG</id>
|
||||||
|
<name>Boeing 737 NG</name>
|
||||||
|
<dir>b737NG</dir>
|
||||||
|
<description>A popular twin-engined narrow body jet</description>
|
||||||
|
<revision type="int">111</revision>
|
||||||
|
<file-size-bytes type="int">860</file-size-bytes>
|
||||||
|
|
||||||
|
<tag>boeing</tag>
|
||||||
|
<tag>jet</tag>
|
||||||
|
<tag>ifr</tag>
|
||||||
|
|
||||||
|
<rating>
|
||||||
|
<FDM type="int">5</FDM>
|
||||||
|
<systems type="int">5</systems>
|
||||||
|
<model type="int">4</model>
|
||||||
|
<cockpit type="int">4</cockpit>
|
||||||
|
</rating>
|
||||||
|
|
||||||
|
<md5>a94ca5704f305b90767f40617d194ed6</md5>
|
||||||
|
<url>http://localhost:2000/catalogTest1/b737.tar.gz</url>
|
||||||
|
</package>
|
||||||
|
|
||||||
|
<package>
|
||||||
|
<id>common-sounds</id>
|
||||||
|
<name>Common sound files for test catalog aircraft</name>
|
||||||
|
<revision>10</revision>
|
||||||
|
<dir>sounds</dir>
|
||||||
|
<url>http://localhost:2000/catalogTest1/common-sounds.zip</url>
|
||||||
|
<file-size-bytes>360</file-size-bytes>
|
||||||
|
<md5>acf9eb89cf396eb42f8823d9cdf17584</md5>
|
||||||
|
</package>
|
||||||
|
</PropertyList>
|
||||||
@@ -10,6 +10,11 @@
|
|||||||
<version>8.0.0</version>
|
<version>8.0.0</version>
|
||||||
<version>8.2.0</version>
|
<version>8.2.0</version>
|
||||||
|
|
||||||
|
<alternate-version>
|
||||||
|
<version>10.*.*</version>
|
||||||
|
<url>http://localhost:2000/catalogTest1/catalog-v10.xml</url>
|
||||||
|
</alternate-version>
|
||||||
|
|
||||||
<package>
|
<package>
|
||||||
<id>alpha</id>
|
<id>alpha</id>
|
||||||
<name>Alpha package</name>
|
<name>Alpha package</name>
|
||||||
|
|||||||
@@ -0,0 +1,178 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<PropertyList>
|
||||||
|
<id>org.flightgear.test.catalog1</id>
|
||||||
|
<description>First test catalog</description>
|
||||||
|
<url>http://localhost:2000/catalogTest1/catalog.xml</url>
|
||||||
|
<catalog-version>4</catalog-version>
|
||||||
|
|
||||||
|
<version>9.1.*</version>
|
||||||
|
|
||||||
|
<package>
|
||||||
|
<id>alpha</id>
|
||||||
|
<name>Alpha package</name>
|
||||||
|
<revision type="int">8</revision>
|
||||||
|
<file-size-bytes type="int">593</file-size-bytes>
|
||||||
|
|
||||||
|
<md5>a469c4b837f0521db48616cfe65ac1ea</md5>
|
||||||
|
<url>http://localhost:2000/catalogTest1/alpha.zip</url>
|
||||||
|
|
||||||
|
<dir>alpha</dir>
|
||||||
|
|
||||||
|
</package>
|
||||||
|
|
||||||
|
<package>
|
||||||
|
<id>c172p</id>
|
||||||
|
<name>Cessna 172-P</name>
|
||||||
|
<dir>c172p</dir>
|
||||||
|
<description>A plane made by Cessna on Jupiter</description>
|
||||||
|
<revision type="int">42</revision>
|
||||||
|
<file-size-bytes type="int">860</file-size-bytes>
|
||||||
|
<author>Standard author</author>
|
||||||
|
|
||||||
|
<tag>cessna</tag>
|
||||||
|
<tag>ga</tag>
|
||||||
|
<tag>piston</tag>
|
||||||
|
<tag>ifr</tag>
|
||||||
|
|
||||||
|
<rating>
|
||||||
|
<FDM type="int">3</FDM>
|
||||||
|
<systems type="int">4</systems>
|
||||||
|
<model type="int">5</model>
|
||||||
|
<cockpit type="int">4</cockpit>
|
||||||
|
</rating>
|
||||||
|
|
||||||
|
<!-- local dependency -->
|
||||||
|
<depends>
|
||||||
|
<id>org.flightgear.test.catalog1.common-sounds</id>
|
||||||
|
<revision>10</revision>
|
||||||
|
</depends>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>exterior</type>
|
||||||
|
<path>thumb-exterior.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-exterior.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>panel</type>
|
||||||
|
<path>thumb-panel.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-panel.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<path>thumb-something.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-something.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<variant>
|
||||||
|
<id>c172p-2d-panel</id>
|
||||||
|
<name>C172 with 2d panel only</name>
|
||||||
|
</variant>
|
||||||
|
|
||||||
|
<variant>
|
||||||
|
<id>c172p-floats</id>
|
||||||
|
<name>C172 with floats</name>
|
||||||
|
<description>A plane with floats</description>
|
||||||
|
<author>Floats variant author</author>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>exterior</type>
|
||||||
|
<path>thumb-exterior-floats.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-exterior-floats.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>panel</type>
|
||||||
|
<path>thumb-panel.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-panel.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<thumbnail>http://foo.bar.com/thumb-floats.png</thumbnail>
|
||||||
|
<thumbnail-path>thumb-floats.png</thumbnail-path>
|
||||||
|
</variant>
|
||||||
|
|
||||||
|
<variant>
|
||||||
|
<id>c172p-skis</id>
|
||||||
|
<name>C172 with skis</name>
|
||||||
|
<description>A plane with skis</description>
|
||||||
|
|
||||||
|
<variant-of>c172p</variant-of>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>exterior</type>
|
||||||
|
<path>thumb-exterior-skis.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-exterior-skis.png</url>
|
||||||
|
</preview>
|
||||||
|
|
||||||
|
<preview>
|
||||||
|
<type>panel</type>
|
||||||
|
<path>thumb-panel.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-panel.png</url>
|
||||||
|
</preview>
|
||||||
|
</variant>
|
||||||
|
|
||||||
|
<variant>
|
||||||
|
<id>c172r</id>
|
||||||
|
<name>C172R</name>
|
||||||
|
<description>Equally good version of the C172</description>
|
||||||
|
<variant-of>_package_</variant-of>
|
||||||
|
<preview>
|
||||||
|
<type>panel</type>
|
||||||
|
<path>thumb-panel.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-panel.png</url>
|
||||||
|
</preview>
|
||||||
|
</variant>
|
||||||
|
|
||||||
|
<variant>
|
||||||
|
<id>c172r-floats</id>
|
||||||
|
<name>C172R-floats</name>
|
||||||
|
<description>Equally good version of the C172 with floats</description>
|
||||||
|
<variant-of>c172r</variant-of>
|
||||||
|
<preview>
|
||||||
|
<type>panel</type>
|
||||||
|
<path>thumb-panel.png</path>
|
||||||
|
<url>http://foo.bar.com/thumb-panel.png</url>
|
||||||
|
</preview>
|
||||||
|
</variant>
|
||||||
|
|
||||||
|
<md5>ec0e2ffdf98d6a5c05c77445e5447ff5</md5>
|
||||||
|
<url>http://localhost:2000/catalogTest1/c172p.zip</url>
|
||||||
|
|
||||||
|
<thumbnail>http://foo.bar.com/thumb-exterior.png</thumbnail>
|
||||||
|
<thumbnail-path>exterior.png</thumbnail-path>
|
||||||
|
</package>
|
||||||
|
|
||||||
|
<package>
|
||||||
|
<id>b737-NG</id>
|
||||||
|
<name>Boeing 737 NG</name>
|
||||||
|
<dir>b737NG</dir>
|
||||||
|
<description>A popular twin-engined narrow body jet</description>
|
||||||
|
<revision type="int">111</revision>
|
||||||
|
<file-size-bytes type="int">860</file-size-bytes>
|
||||||
|
|
||||||
|
<tag>boeing</tag>
|
||||||
|
<tag>jet</tag>
|
||||||
|
<tag>ifr</tag>
|
||||||
|
|
||||||
|
<rating>
|
||||||
|
<FDM type="int">5</FDM>
|
||||||
|
<systems type="int">5</systems>
|
||||||
|
<model type="int">4</model>
|
||||||
|
<cockpit type="int">4</cockpit>
|
||||||
|
</rating>
|
||||||
|
|
||||||
|
<md5>a94ca5704f305b90767f40617d194ed6</md5>
|
||||||
|
<url>http://localhost:2000/catalogTest1/b737.tar.gz</url>
|
||||||
|
</package>
|
||||||
|
|
||||||
|
<package>
|
||||||
|
<id>common-sounds</id>
|
||||||
|
<name>Common sound files for test catalog aircraft</name>
|
||||||
|
<revision>10</revision>
|
||||||
|
<dir>sounds</dir>
|
||||||
|
<url>http://localhost:2000/catalogTest1/common-sounds.zip</url>
|
||||||
|
<file-size-bytes>360</file-size-bytes>
|
||||||
|
<md5>acf9eb89cf396eb42f8823d9cdf17584</md5>
|
||||||
|
</package>
|
||||||
|
</PropertyList>
|
||||||
Reference in New Issue
Block a user