Files
simgear/simgear/package/Root.cxx
T

263 lines
6.1 KiB
C++

// Copyright (C) 2013 James Turner - zakalawe@mac.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include <simgear/package/Root.hxx>
#include <boost/foreach.hpp>
#include <cstring>
#include <simgear/debug/logstream.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/io/HTTPRequest.hxx>
#include <simgear/io/HTTPClient.hxx>
#include <simgear/misc/sg_dir.hxx>
#include <simgear/structure/exception.hxx>
#include <simgear/package/Package.hxx>
#include <simgear/package/Install.hxx>
#include <simgear/package/Catalog.hxx>
namespace simgear {
namespace pkg {
void Root::setMaxAgeSeconds(int seconds)
{
m_maxAgeSeconds = seconds;
}
void Root::setHTTPClient(HTTP::Client* aHTTP)
{
m_http = aHTTP;
}
HTTP::Client* Root::getHTTPClient() const
{
return m_http;
}
Root::Root(const SGPath& aPath) :
m_path(aPath),
m_http(NULL),
m_maxAgeSeconds(60 * 60 * 24),
m_delegate(NULL)
{
if (getenv("LOCALE")) {
m_locale = getenv("LOCALE");
}
Dir d(aPath);
if (!d.exists()) {
d.create(0755);
return;
}
BOOST_FOREACH(SGPath c, d.children(Dir::TYPE_DIR)) {
Catalog* cat = Catalog::createFromPath(this, c);
if (cat) {
m_catalogs[cat->id()] = cat;
}
} // of child directories iteration
}
Root::~Root()
{
}
Catalog* Root::getCatalogById(const std::string& aId) const
{
CatalogDict::const_iterator it = m_catalogs.find(aId);
if (it == m_catalogs.end()) {
return NULL;
}
return it->second;
}
Package* Root::getPackageById(const std::string& aName) const
{
size_t lastDot = aName.rfind('.');
Package* pkg = NULL;
if (lastDot == std::string::npos) {
// naked package ID
CatalogDict::const_iterator it = m_catalogs.begin();
for (; it != m_catalogs.end(); ++it) {
pkg = it->second->getPackageById(aName);
if (pkg) {
return pkg;
}
}
return NULL;
}
std::string catalogId = aName.substr(0, lastDot);
std::string id = aName.substr(lastDot + 1);
Catalog* catalog = getCatalogById(catalogId);
if (!catalog) {
return NULL;
}
return catalog->getPackageById(id);
}
CatalogList Root::catalogs() const
{
CatalogList r;
CatalogDict::const_iterator it = m_catalogs.begin();
for (; it != m_catalogs.end(); ++it) {
r.push_back(it->second);
}
return r;
}
PackageList
Root::packagesMatching(const SGPropertyNode* aFilter) const
{
PackageList r;
CatalogDict::const_iterator it = m_catalogs.begin();
for (; it != m_catalogs.end(); ++it) {
PackageList r2(it->second->packagesMatching(aFilter));
r.insert(r.end(), r2.begin(), r2.end());
}
return r;
}
PackageList
Root::packagesNeedingUpdate() const
{
PackageList r;
CatalogDict::const_iterator it = m_catalogs.begin();
for (; it != m_catalogs.end(); ++it) {
PackageList r2(it->second->packagesNeedingUpdate());
r.insert(r.end(), r2.begin(), r2.end());
}
return r;
}
void Root::refresh(bool aForce)
{
CatalogDict::iterator it = m_catalogs.begin();
for (; it != m_catalogs.end(); ++it) {
if (aForce || (it->second->ageInSeconds() > m_maxAgeSeconds)) {
it->second->refresh();
}
}
}
void Root::setLocale(const std::string& aLocale)
{
m_locale = aLocale;
}
std::string Root::getLocale() const
{
return m_locale;
}
void Root::scheduleToUpdate(Install* aInstall)
{
if (!aInstall) {
sg_exception("missing argument to scheduleToUpdate");
}
PackageList deps = aInstall->package()->dependencies();
BOOST_FOREACH(Package* dep, deps) {
// will internally schedule for update if required
// hence be careful, this method is re-entered in here!
dep->install();
}
bool wasEmpty = m_updateDeque.empty();
m_updateDeque.push_back(aInstall);
if (wasEmpty) {
aInstall->startUpdate();
}
}
void Root::startInstall(Install* aInstall)
{
if (m_delegate) {
m_delegate->startInstall(aInstall);
}
}
void Root::installProgress(Install* aInstall, unsigned int aBytes, unsigned int aTotal)
{
if (m_delegate) {
m_delegate->installProgress(aInstall, aBytes, aTotal);
}
}
void Root::startNext(Install* aCurrent)
{
if (m_updateDeque.front() != aCurrent) {
SG_LOG(SG_GENERAL, SG_ALERT, "current install of package not head of the deque");
} else {
m_updateDeque.pop_front();
}
if (!m_updateDeque.empty()) {
m_updateDeque.front()->startUpdate();
}
}
void Root::finishInstall(Install* aInstall)
{
if (m_delegate) {
m_delegate->finishInstall(aInstall);
}
startNext(aInstall);
}
void Root::failedInstall(Install* aInstall, Delegate::FailureCode aReason)
{
SG_LOG(SG_GENERAL, SG_ALERT, "failed to install package:"
<< aInstall->package()->id() << ":" << aReason);
if (m_delegate) {
m_delegate->failedInstall(aInstall, aReason);
}
startNext(aInstall);
}
void Root::catalogRefreshBegin(Catalog* aCat)
{
m_refreshing.insert(aCat);
}
void Root::catalogRefreshComplete(Catalog* aCat, bool aSuccess)
{
m_refreshing.erase(aCat);
if (m_refreshing.empty()) {
if (m_delegate) {
m_delegate->refreshComplete();
}
}
}
} // of namespace pkg
} // of namespace simgear