HaikuDepot: Fix #10189.

- Move InstallPackageAction's _FindPackageByName to PackageAction, so
UninstallPackageAction can make use of it as well.

- Rename DownloadProgressListener to PackageProgressListener and add
hooks for the package manager's DownloadProgressComplete,
StartApplyingChanges and ApplyingChangesDone events.

- InstallPackageAction implements DownloadProgressComplete in order to
gather all dependent packages that were downloaded as part of the
installation request. These are then set to active, or reset to available
depending on the outcome. Fixes the problem reported in #10189.

- UninstallPackageAction now implements the aforementioned ApplyingChanges
hooks in order to track all packages to be uninstalled as part of the
transaction. Upon completion, they are all accordingly marked as Available.
Previously the state wasn't correctly reset for any dependent packages that
were also removed as a consequence of the requested package's removal.
This commit is contained in:
Rene Gollent
2013-11-10 18:44:40 -05:00
parent b781fcec00
commit 1c56f25236
4 changed files with 139 additions and 38 deletions
+20
View File
@@ -8,6 +8,7 @@
#include "PackageAction.h" #include "PackageAction.h"
#include "Model.h"
#include "PackageManager.h" #include "PackageManager.h"
@@ -45,3 +46,22 @@ PackageAction::~PackageAction()
} }
PackageInfoRef
PackageAction::FindPackageByName(const BString& name)
{
Model* model = GetModel();
const DepotList& depots = model->Depots();
// TODO: optimize!
for (int32 i = 0; i < depots.CountItems(); i++) {
const DepotInfo& depot = depots.ItemAtFast(i);
const PackageList& packages = depot.Packages();
for (int32 j = 0; j < packages.CountItems(); j++) {
PackageInfoRef info = packages.ItemAtFast(j);
if (info->Title() == name)
return info;
}
}
return PackageInfoRef();
}
+3
View File
@@ -43,6 +43,9 @@ public:
PackageInfoRef Package() const PackageInfoRef Package() const
{ return fPackage; } { return fPackage; }
protected:
PackageInfoRef FindPackageByName(const BString& name);
protected: protected:
PackageManager* fPackageManager; PackageManager* fPackageManager;
+99 -30
View File
@@ -44,19 +44,50 @@ using BPackageKit::BSolverPackage;
using BPackageKit::BSolverRepository; using BPackageKit::BSolverRepository;
// #pragma mark - DownloadProgressListener typedef std::set<PackageInfoRef> PackageInfoSet;
DownloadProgressListener::~DownloadProgressListener() // #pragma mark - PackageProgressListener
PackageProgressListener::~PackageProgressListener()
{ {
} }
void
PackageProgressListener::DownloadProgressChanged(const char* packageName,
float progress)
{
}
void
PackageProgressListener::DownloadProgressComplete(const char* packageName)
{
}
void
PackageProgressListener::StartApplyingChanges(
BPackageManager::InstalledRepository& repository)
{
}
void
PackageProgressListener::ApplyingChangesDone(
BPackageManager::InstalledRepository& repository)
{
}
// #pragma mark - InstallPackageAction // #pragma mark - InstallPackageAction
class InstallPackageAction : public PackageAction, class InstallPackageAction : public PackageAction,
private DownloadProgressListener { private PackageProgressListener {
public: public:
InstallPackageAction(PackageInfoRef package, Model* model) InstallPackageAction(PackageInfoRef package, Model* model)
: :
@@ -87,17 +118,20 @@ public:
ex.Details().String()); ex.Details().String());
return ex.Error(); return ex.Error();
} catch (BAbortedByUserException ex) { } catch (BAbortedByUserException ex) {
_SetDownloadedPackagesState(NONE);
return B_OK; return B_OK;
} catch (BNothingToDoException ex) { } catch (BNothingToDoException ex) {
return B_OK; return B_OK;
} catch (BException ex) { } catch (BException ex) {
fprintf(stderr, "Exception occurred while installing package " fprintf(stderr, "Exception occurred while installing package "
"%s: %s\n", packageName, ex.Message().String()); "%s: %s\n", packageName, ex.Message().String());
_SetDownloadedPackagesState(NONE);
return B_ERROR;; return B_ERROR;;
} }
fPackageManager->RemoveProgressListener(this); fPackageManager->RemoveProgressListener(this);
ref->SetState(ACTIVATED);
_SetDownloadedPackagesState(ACTIVATED);
return B_OK; return B_OK;
} }
@@ -107,11 +141,11 @@ public:
float progress) float progress)
{ {
bigtime_t now = system_time(); bigtime_t now = system_time();
if (now - fLastDownloadUpdate > 250000) { if (now - fLastDownloadUpdate > 250000 || progress == 1.0) {
BString tempName(packageName); BString tempName(packageName);
tempName.Truncate(tempName.FindFirst('-')); tempName.Truncate(tempName.FindFirst('-'));
// strip version suffix off package filename // strip version suffix off package filename
PackageInfoRef ref(_FindPackageByName(tempName)); PackageInfoRef ref(FindPackageByName(tempName));
if (ref.Get() != NULL) { if (ref.Get() != NULL) {
ref->SetDownloadProgress(progress); ref->SetDownloadProgress(progress);
fLastDownloadUpdate = now; fLastDownloadUpdate = now;
@@ -119,35 +153,38 @@ public:
} }
} }
virtual void DownloadProgressComplete(const char* packageName)
{
BString tempName(packageName);
tempName.Truncate(tempName.FindFirst('-'));
// strip version suffix off package filename
PackageInfoRef ref(FindPackageByName(tempName));
if (ref.Get() != NULL) {
ref->SetDownloadProgress(1.0);
fDownloadedPackages.insert(ref);
}
}
private: private:
PackageInfoRef _FindPackageByName(const BString& name) void _SetDownloadedPackagesState(PackageState state)
{ {
Model* model = GetModel(); for (PackageInfoSet::iterator it = fDownloadedPackages.begin();
const DepotList& depots = model->Depots(); it != fDownloadedPackages.end(); ++it) {
// TODO: optimize! (*it)->SetState(state);
for (int32 i = 0; i < depots.CountItems(); i++) {
const DepotInfo& depot = depots.ItemAtFast(i);
const PackageList& packages = depot.Packages();
for (int32 j = 0; j < packages.CountItems(); j++) {
PackageInfoRef info = packages.ItemAtFast(j);
if (info->Title() == name)
return info;
}
} }
return PackageInfoRef();
} }
private: private:
bigtime_t fLastDownloadUpdate; bigtime_t fLastDownloadUpdate;
PackageInfoSet fDownloadedPackages;
}; };
// #pragma mark - UninstallPackageAction // #pragma mark - UninstallPackageAction
class UninstallPackageAction : public PackageAction { class UninstallPackageAction : public PackageAction,
private PackageProgressListener {
public: public:
UninstallPackageAction(PackageInfoRef package, Model* model) UninstallPackageAction(PackageInfoRef package, Model* model)
: :
@@ -165,6 +202,7 @@ public:
fPackageManager->Init(BPackageManager::B_ADD_INSTALLED_REPOSITORIES); fPackageManager->Init(BPackageManager::B_ADD_INSTALLED_REPOSITORIES);
PackageInfoRef ref(Package()); PackageInfoRef ref(Package());
fPackageManager->SetCurrentActionPackage(ref, false); fPackageManager->SetCurrentActionPackage(ref, false);
fPackageManager->AddProgressListener(this);
const char* packageName = ref->Title().String(); const char* packageName = ref->Title().String();
try { try {
fPackageManager->Uninstall(&packageName, 1); fPackageManager->Uninstall(&packageName, 1);
@@ -183,10 +221,36 @@ public:
return B_ERROR; return B_ERROR;
} }
fPackageManager->RemoveProgressListener(this);
ref->SetState(NONE); ref->SetState(NONE);
return B_OK; return B_OK;
} }
void StartApplyingChanges(
BPackageManager::InstalledRepository& repository)
{
BPackageManager::InstalledRepository::PackageList& packages
= repository.PackagesToDeactivate();
for (int32 i = 0; i < packages.CountItems(); i++) {
PackageInfoRef ref(FindPackageByName(packages.ItemAt(i)
->Name()));
if (ref.Get() != NULL)
fRemovedPackages.Add(ref);
}
}
void ApplyingChangesDone(
BPackageManager::InstalledRepository& repository)
{
for (int32 i = 0; i < fRemovedPackages.CountItems(); i++)
fRemovedPackages.ItemAt(i)->SetState(NONE);
}
private:
PackageList fRemovedPackages;
}; };
@@ -298,16 +362,16 @@ PackageManager::DownloadPackage(const BString& fileURL,
void void
PackageManager::AddProgressListener(DownloadProgressListener* listener) PackageManager::AddProgressListener(PackageProgressListener* listener)
{ {
fDownloadProgressListeners.AddItem(listener); fPackageProgressListeners.AddItem(listener);
} }
void void
PackageManager::RemoveProgressListener(DownloadProgressListener* listener) PackageManager::RemoveProgressListener(PackageProgressListener* listener)
{ {
fDownloadProgressListeners.RemoveItem(listener); fPackageProgressListeners.RemoveItem(listener);
} }
@@ -375,8 +439,8 @@ void
PackageManager::ProgressPackageDownloadActive(const char* packageName, PackageManager::ProgressPackageDownloadActive(const char* packageName,
float completionPercentage) float completionPercentage)
{ {
for (int32 i = 0; i < fDownloadProgressListeners.CountItems(); i++) { for (int32 i = 0; i < fPackageProgressListeners.CountItems(); i++) {
fDownloadProgressListeners.ItemAt(i)->DownloadProgressChanged( fPackageProgressListeners.ItemAt(i)->DownloadProgressChanged(
packageName, completionPercentage); packageName, completionPercentage);
} }
} }
@@ -385,7 +449,10 @@ PackageManager::ProgressPackageDownloadActive(const char* packageName,
void void
PackageManager::ProgressPackageDownloadComplete(const char* packageName) PackageManager::ProgressPackageDownloadComplete(const char* packageName)
{ {
// TODO: implement for (int32 i = 0; i < fPackageProgressListeners.CountItems(); i++) {
fPackageProgressListeners.ItemAt(i)->DownloadProgressComplete(
packageName);
}
} }
@@ -406,7 +473,8 @@ PackageManager::ProgressPackageChecksumComplete(const char* title)
void void
PackageManager::ProgressStartApplyingChanges(InstalledRepository& repository) PackageManager::ProgressStartApplyingChanges(InstalledRepository& repository)
{ {
// TODO: implement for (int32 i = 0; i < fPackageProgressListeners.CountItems(); i++)
fPackageProgressListeners.ItemAt(i)->StartApplyingChanges(repository);
} }
@@ -421,7 +489,8 @@ PackageManager::ProgressTransactionCommitted(InstalledRepository& repository,
void void
PackageManager::ProgressApplyingChangesDone(InstalledRepository& repository) PackageManager::ProgressApplyingChangesDone(InstalledRepository& repository)
{ {
// TODO: implement for (int32 i = 0; i < fPackageProgressListeners.CountItems(); i++)
fPackageProgressListeners.ItemAt(i)->ApplyingChangesDone(repository);
} }
+17 -8
View File
@@ -36,17 +36,26 @@ using BPackageKit::BPrivate::BDaemonClient;
using BPackageKit::BManager::BPrivate::BPackageManager; using BPackageKit::BManager::BPrivate::BPackageManager;
class DownloadProgressListener { class PackageProgressListener {
public: public:
virtual ~DownloadProgressListener(); virtual ~PackageProgressListener();
virtual void DownloadProgressChanged( virtual void DownloadProgressChanged(
const char* packageName, const char* packageName,
float progress) = 0; float progress);
virtual void DownloadProgressComplete(
const char* packageName);
virtual void StartApplyingChanges(
BPackageManager::InstalledRepository&
repository);
virtual void ApplyingChangesDone(
BPackageManager::InstalledRepository&
repository);
}; };
typedef BObjectList<DownloadProgressListener> DownloadProgressListenerList; typedef BObjectList<PackageProgressListener> PackageProgressListenerList;
class PackageManager : public BPackageManager, class PackageManager : public BPackageManager,
@@ -71,9 +80,9 @@ public:
const BString& checksum); const BString& checksum);
void AddProgressListener( void AddProgressListener(
DownloadProgressListener* listener); PackageProgressListener* listener);
void RemoveProgressListener( void RemoveProgressListener(
DownloadProgressListener* listener); PackageProgressListener* listener);
private: private:
// UserInteractionHandler // UserInteractionHandler
@@ -122,8 +131,8 @@ private:
BPackageKit::BSolverPackage* BPackageKit::BSolverPackage*
fCurrentUninstallPackage; fCurrentUninstallPackage;
DownloadProgressListenerList PackageProgressListenerList
fDownloadProgressListeners; fPackageProgressListeners;
}; };
#endif // PACKAGE_MANAGER_H #endif // PACKAGE_MANAGER_H