Catalog install feedback.

- also support removing (uninstalling) a catalog and
all installs relating to it.
This commit is contained in:
James Turner
2015-03-12 14:27:29 +00:00
parent a67a984d29
commit 596591bb64
7 changed files with 129 additions and 8 deletions

View File

@@ -45,6 +45,8 @@ public:
HTTP::Request(aUrl),
m_owner(aOwner)
{
// refreshing
m_owner->changeStatus(Delegate::FAIL_IN_PROGRESS);
}
protected:
@@ -90,7 +92,7 @@ protected:
time(&m_owner->m_retrievedTime);
m_owner->writeTimestamp();
m_owner->refreshComplete(Delegate::FAIL_SUCCESS);
m_owner->refreshComplete(Delegate::CATALOG_REFRESHED);
}
private:
@@ -112,6 +114,7 @@ private:
Catalog::Catalog(Root *aRoot) :
m_root(aRoot),
m_status(Delegate::FAIL_UNKNOWN),
m_retrievedTime(0)
{
}
@@ -154,12 +157,39 @@ CatalogRef Catalog::createFromPath(Root* aRoot, const SGPath& aPath)
CatalogRef c = new Catalog(aRoot);
c->m_installRoot = aPath;
c->parseProps(props);
c->parseProps(props); // will set status
c->parseTimestamp();
return c;
}
bool Catalog::uninstall()
{
bool ok;
bool atLeastOneFailure = false;
BOOST_FOREACH(PackageRef p, installedPackages()) {
ok = p->existingInstall()->uninstall();
if (!ok) {
SG_LOG(SG_GENERAL, SG_WARN, "uninstall of package " <<
p->id() << " failed");
// continue trying other packages, bailing out here
// gains us nothing
atLeastOneFailure = true;
}
}
Dir d(m_installRoot);
ok = d.remove(true /* recursive */);
if (!ok) {
atLeastOneFailure = true;
}
changeStatus(atLeastOneFailure ? Delegate::FAIL_FILESYSTEM
: Delegate::FAIL_SUCCESS);
return ok;
}
PackageList const&
Catalog::packages() const
{
@@ -226,6 +256,7 @@ InstallRef Catalog::installForPackage(PackageRef pkg) const
void Catalog::refresh()
{
Downloader* dl = new Downloader(this, url());
// will iupdate status to IN_PROGRESS
m_root->makeHTTPRequest(dl);
m_root->catalogRefreshBegin(this);
}
@@ -294,6 +325,9 @@ 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
@@ -372,6 +406,7 @@ std::string Catalog::getLocalisedString(const SGPropertyNode* aRoot, const char*
void Catalog::refreshComplete(Delegate::FailureCode aReason)
{
m_root->catalogRefreshComplete(this, aReason);
changeStatus(aReason);
}
void Catalog::registerInstall(Install* ins)
@@ -392,6 +427,26 @@ void Catalog::unregisterInstall(Install* ins)
m_installed.erase(ins->package());
}
void Catalog::changeStatus(Delegate::FailureCode newStatus)
{
if (m_status == newStatus) {
return;
}
m_status = newStatus;
m_statusCallbacks(this);
}
void Catalog::addStatusCallback(const Callback& cb)
{
m_statusCallbacks.push_back(cb);
}
Delegate::FailureCode Catalog::status() const
{
return m_status;
}
} // of namespace pkg
} // of namespace simgear

View File

@@ -22,11 +22,14 @@
#include <ctime>
#include <map>
#include <boost/bind.hpp>
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props.hxx>
#include <simgear/structure/SGReferenced.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/structure/function_list.hxx>
#include <simgear/package/Delegate.hxx>
@@ -63,6 +66,11 @@ public:
Root* root() const
{ return m_root;};
/**
* uninstall this catalog entirely, including all installed packages
*/
bool uninstall();
/**
* perform a refresh of the catalog contents
*/
@@ -115,6 +123,18 @@ public:
* access the raw property data in the catalog
*/
SGPropertyNode* properties() const;
Delegate::FailureCode status() const;
typedef boost::function<void(Catalog*)> Callback;
void addStatusCallback(const Callback& cb);
template<class C>
void addStatusCallback(C* instance, void (C::*mem_func)(Catalog*))
{
return addStatusCallback(boost::bind(mem_func, instance, _1));
}
private:
Catalog(Root* aRoot);
@@ -134,11 +154,14 @@ private:
std::string getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const;
void changeStatus(Delegate::FailureCode newStatus);
Root* m_root;
SGPropertyNode_ptr m_props;
SGPath m_installRoot;
std::string m_url;
Delegate::FailureCode m_status;
PackageList m_packages;
time_t m_retrievedTime;
@@ -149,6 +172,8 @@ private:
// since it is only cleaned up in the Install destructor
typedef std::map<PackageRef, Install*> PackageInstallDict;
PackageInstallDict m_installed;
function_list<Callback> m_statusCallbacks;
};
} // of namespace pkg

View File

@@ -42,7 +42,8 @@ public:
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
CATALOG_REFRESHED
} FailureCode;

View File

@@ -313,11 +313,21 @@ void Install::startUpdate()
m_package->catalog()->root()->startInstall(this);
}
void Install::uninstall()
bool Install::uninstall()
{
Dir d(m_path);
d.remove(true);
if (!d.remove(true)) {
SG_LOG(SG_GENERAL, SG_ALERT, "package uninstall failed: couldn't remove path " << m_path);
return false;
}
m_package->catalog()->unregisterInstall(this);
return true;
}
bool Install::isDownloading() const
{
return (m_download != NULL);
}
//------------------------------------------------------------------------------

View File

@@ -73,9 +73,11 @@ public:
bool hasUpdate() const;
void startUpdate();
void uninstall();
bool uninstall();
bool isDownloading() const;
/**
* Set the handler to be called when the installation successfully
* completes.

View File

@@ -336,6 +336,28 @@ void Root::catalogRefreshComplete(CatalogRef aCat, Delegate::FailureCode aReason
}
}
bool Root::removeCatalogById(const std::string& aId)
{
CatalogDict::iterator catIt = d->catalogs.find(aId);
if (catIt == d->catalogs.end()) {
SG_LOG(SG_GENERAL, SG_WARN, "removeCatalogById: unknown ID:" << aId);
return false;
}
CatalogRef cat = catIt->second;
// drop the reference
d->catalogs.erase(catIt);
bool ok = cat->uninstall();
if (!ok) {
SG_LOG(SG_GENERAL, SG_WARN, "removeCatalogById: catalog :" << aId
<< "failed to uninstall");
}
return ok;
}
} // of namespace pkg
} // of namespace simgear

View File

@@ -109,6 +109,12 @@ public:
CatalogRef getCatalogById(const std::string& aId) const;
void scheduleToUpdate(InstallRef aInstall);
/**
* remove a catalog. Will uninstall all packages originating
* from the catalog too.
*/
bool removeCatalogById(const std::string& aId);
private:
friend class Install;
friend class Catalog;