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:
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user