HaikuDepot: notify work status from main window
[haiku.git] / src / apps / haikudepot / model / PackageManager.cpp
blobe94e3499c3a26f79377ca02186e2bc3feaf6c8b9
1 /*
2 * Copyright 2013-2017, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Ingo Weinhold <ingo_weinhold@gmx.de>
7 * Stephan Aßmus <superstippi@gmx.de>
8 * Rene Gollent <rene@gollent.com>
9 * Julian Harnath <julian.harnath@rwth-aachen.de>
13 #include "PackageManager.h"
15 #include <stdio.h>
17 #include <Alert.h>
18 #include <Catalog.h>
19 #include <Entry.h>
20 #include <FindDirectory.h>
21 #include <Path.h>
22 #include <Roster.h>
24 #include <package/DownloadFileRequest.h>
25 #include <package/manager/Exceptions.h>
26 #include <package/RefreshRepositoryRequest.h>
27 #include <package/hpkg/NoErrorOutput.h>
28 #include <package/hpkg/PackageContentHandler.h>
29 #include <package/hpkg/PackageEntry.h>
30 #include <package/hpkg/PackageEntryAttribute.h>
31 #include <package/hpkg/PackageInfoAttributeValue.h>
32 #include <package/hpkg/PackageReader.h>
33 #include <package/solver/SolverPackage.h>
34 #include <package/solver/SolverProblem.h>
35 #include <package/solver/SolverProblemSolution.h>
37 #include "AutoDeleter.h"
38 #include "AutoLocker.h"
39 #include "Model.h"
40 #include "PackageInfo.h"
41 #include "ProblemWindow.h"
42 #include "ResultWindow.h"
45 #undef B_TRANSLATION_CONTEXT
46 #define B_TRANSLATION_CONTEXT "PackageManager"
49 using namespace BPackageKit;
50 using namespace BPackageKit::BPrivate;
51 using namespace BPackageKit::BManager::BPrivate;
53 using BPackageKit::BRefreshRepositoryRequest;
54 using BPackageKit::DownloadFileRequest;
55 using BPackageKit::BSolver;
56 using BPackageKit::BSolverPackage;
57 using BPackageKit::BSolverRepository;
58 using BPackageKit::BHPKG::BNoErrorOutput;
59 using BPackageKit::BHPKG::BPackageContentHandler;
60 using BPackageKit::BHPKG::BPackageEntry;
61 using BPackageKit::BHPKG::BPackageEntryAttribute;
62 using BPackageKit::BHPKG::BPackageInfoAttributeValue;
63 using BPackageKit::BHPKG::BPackageReader;
66 typedef std::set<PackageInfoRef> PackageInfoSet;
69 // #pragma mark - PackageProgressListener
72 PackageProgressListener::~PackageProgressListener()
77 void
78 PackageProgressListener::DownloadProgressChanged(const char* packageName,
79 float progress)
84 void
85 PackageProgressListener::DownloadProgressComplete(const char* packageName)
90 void
91 PackageProgressListener::ConfirmedChanges(
92 BPackageManager::InstalledRepository& repository)
97 void
98 PackageProgressListener::StartApplyingChanges(
99 BPackageManager::InstalledRepository& repository)
104 void
105 PackageProgressListener::ApplyingChangesDone(
106 BPackageManager::InstalledRepository& repository)
112 // #pragma mark - InstallPackageAction
115 class InstallPackageAction : public PackageAction,
116 private PackageProgressListener {
117 public:
118 InstallPackageAction(PackageInfoRef package, Model* model)
120 PackageAction(PACKAGE_ACTION_INSTALL, package, model),
121 fLastDownloadUpdate(0)
125 virtual const char* Label() const
127 return B_TRANSLATE("Install");
130 virtual status_t Perform()
132 fPackageManager->Init(BPackageManager::B_ADD_INSTALLED_REPOSITORIES
133 | BPackageManager::B_ADD_REMOTE_REPOSITORIES
134 | BPackageManager::B_REFRESH_REPOSITORIES);
135 PackageInfoRef ref(Package());
136 PackageState state = ref->State();
137 ref->SetState(PENDING);
139 fPackageManager->SetCurrentActionPackage(ref, true);
140 fPackageManager->AddProgressListener(this);
142 BString packageName;
143 if (ref->IsLocalFile())
144 packageName = ref->LocalFilePath();
145 else
146 packageName = ref->Name();
148 const char* packageNameString = packageName.String();
149 try {
150 fPackageManager->Install(&packageNameString, 1);
151 } catch (BFatalErrorException ex) {
152 BString errorString;
153 errorString.SetToFormat(
154 "Fatal error occurred while installing package %s: "
155 "%s (%s)\n", packageNameString, ex.Message().String(),
156 ex.Details().String());
157 BAlert* alert(new(std::nothrow) BAlert(B_TRANSLATE("Fatal error"),
158 errorString, B_TRANSLATE("Close"), NULL, NULL,
159 B_WIDTH_AS_USUAL, B_STOP_ALERT));
160 if (alert != NULL)
161 alert->Go();
162 _SetDownloadedPackagesState(NONE);
163 ref->SetState(state);
164 return ex.Error();
165 } catch (BAbortedByUserException ex) {
166 fprintf(stderr, "Installation of package "
167 "%s aborted by user: %s\n", packageNameString,
168 ex.Message().String());
169 _SetDownloadedPackagesState(NONE);
170 ref->SetState(state);
171 return B_OK;
172 } catch (BNothingToDoException ex) {
173 fprintf(stderr, "Nothing to do while installing package "
174 "%s: %s\n", packageNameString, ex.Message().String());
175 return B_OK;
176 } catch (BException ex) {
177 fprintf(stderr, "Exception occurred while installing package "
178 "%s: %s\n", packageNameString, ex.Message().String());
179 _SetDownloadedPackagesState(NONE);
180 ref->SetState(state);
181 return B_ERROR;
184 fPackageManager->RemoveProgressListener(this);
186 _SetDownloadedPackagesState(ACTIVATED);
188 return B_OK;
191 // DownloadProgressListener
192 virtual void DownloadProgressChanged(const char* packageName,
193 float progress)
195 bigtime_t now = system_time();
196 if (now - fLastDownloadUpdate > 250000 || progress == 1.0) {
197 BString tempName(packageName);
198 tempName.Truncate(tempName.FindFirst('-'));
199 // strip version suffix off package filename
200 PackageInfoRef ref(FindPackageByName(tempName));
201 if (ref.Get() != NULL) {
202 ref->SetDownloadProgress(progress);
203 fLastDownloadUpdate = now;
208 virtual void DownloadProgressComplete(const char* packageName)
210 BString tempName(packageName);
211 tempName.Truncate(tempName.FindFirst('-'));
212 // strip version suffix off package filename
213 PackageInfoRef ref(FindPackageByName(tempName));
214 if (ref.Get() != NULL) {
215 ref->SetDownloadProgress(1.0);
216 fDownloadedPackages.insert(ref);
220 virtual void ConfirmedChanges(BPackageManager::InstalledRepository&
221 repository)
223 BPackageManager::InstalledRepository::PackageList& activationList =
224 repository.PackagesToActivate();
226 BSolverPackage* package = NULL;
227 for (int32 i = 0; (package = activationList.ItemAt(i)); i++) {
228 PackageInfoRef ref(FindPackageByName(package->Info().Name()));
229 if (ref.Get() != NULL)
230 ref->SetState(PENDING);
234 private:
235 void _SetDownloadedPackagesState(PackageState state)
237 for (PackageInfoSet::iterator it = fDownloadedPackages.begin();
238 it != fDownloadedPackages.end(); ++it) {
239 (*it)->SetState(state);
243 private:
244 bigtime_t fLastDownloadUpdate;
245 PackageInfoSet fDownloadedPackages;
249 // #pragma mark - UninstallPackageAction
252 class UninstallPackageAction : public PackageAction,
253 private PackageProgressListener {
254 public:
255 UninstallPackageAction(PackageInfoRef package, Model* model)
257 PackageAction(PACKAGE_ACTION_UNINSTALL, package, model)
261 virtual const char* Label() const
263 return B_TRANSLATE("Uninstall");
266 virtual status_t Perform()
268 fPackageManager->Init(BPackageManager::B_ADD_INSTALLED_REPOSITORIES);
269 PackageInfoRef ref(Package());
270 PackageState state = ref->State();
271 fPackageManager->SetCurrentActionPackage(ref, false);
272 fPackageManager->AddProgressListener(this);
273 const char* packageName = ref->Name().String();
274 try {
275 fPackageManager->Uninstall(&packageName, 1);
276 } catch (BFatalErrorException ex) {
277 BString errorString;
278 errorString.SetToFormat(
279 "Fatal error occurred while uninstalling package %s: "
280 "%s (%s)\n", packageName, ex.Message().String(),
281 ex.Details().String());
282 BAlert* alert(new(std::nothrow) BAlert(B_TRANSLATE("Fatal error"),
283 errorString, B_TRANSLATE("Close"), NULL, NULL,
284 B_WIDTH_AS_USUAL, B_STOP_ALERT));
285 if (alert != NULL)
286 alert->Go();
287 ref->SetState(state);
288 return ex.Error();
289 } catch (BAbortedByUserException ex) {
290 return B_OK;
291 } catch (BNothingToDoException ex) {
292 return B_OK;
293 } catch (BException ex) {
294 fprintf(stderr, "Exception occurred while uninstalling package "
295 "%s: %s\n", packageName, ex.Message().String());
296 ref->SetState(state);
297 return B_ERROR;
300 fPackageManager->RemoveProgressListener(this);
302 ref->SetState(NONE);
304 return B_OK;
307 void StartApplyingChanges(
308 BPackageManager::InstalledRepository& repository)
310 BPackageManager::InstalledRepository::PackageList& packages
311 = repository.PackagesToDeactivate();
312 for (int32 i = 0; i < packages.CountItems(); i++) {
313 PackageInfoRef ref(FindPackageByName(packages.ItemAt(i)
314 ->Name()));
315 if (ref.Get() != NULL)
316 fRemovedPackages.Add(ref);
320 void ApplyingChangesDone(
321 BPackageManager::InstalledRepository& repository)
323 for (int32 i = 0; i < fRemovedPackages.CountItems(); i++)
324 fRemovedPackages.ItemAt(i)->SetState(NONE);
327 private:
328 PackageList fRemovedPackages;
332 // #pragma mark - OpenPackageAction
335 struct DeskbarLink {
336 DeskbarLink()
340 DeskbarLink(const BString& path, const BString& link)
342 path(path),
343 link(link)
347 DeskbarLink(const DeskbarLink& other)
349 path(other.path),
350 link(other.link)
354 DeskbarLink& operator=(const DeskbarLink& other)
356 if (this == &other)
357 return *this;
358 path = other.path;
359 link = other.link;
360 return *this;
363 bool operator==(const DeskbarLink& other)
365 return path == other.path && link == other.link;
368 bool operator!=(const DeskbarLink& other)
370 return !(*this == other);
373 BString path;
374 BString link;
378 typedef List<DeskbarLink, false> DeskbarLinkList;
381 class DeskbarLinkFinder : public BPackageContentHandler {
382 public:
383 DeskbarLinkFinder(DeskbarLinkList& foundLinks)
385 fDeskbarLinks(foundLinks)
389 virtual status_t HandleEntry(BPackageEntry* entry)
391 BString path = MakePath(entry);
392 if (path.FindFirst("data/deskbar/menu") == 0
393 && entry->SymlinkPath() != NULL) {
394 printf("found deskbar entry: %s -> %s\n", path.String(),
395 entry->SymlinkPath());
396 fDeskbarLinks.Add(DeskbarLink(path, entry->SymlinkPath()));
398 return B_OK;
401 virtual status_t HandleEntryAttribute(BPackageEntry* entry,
402 BPackageEntryAttribute* attribute)
404 return B_OK;
407 virtual status_t HandleEntryDone(BPackageEntry* entry)
409 return B_OK;
412 virtual status_t HandlePackageAttribute(
413 const BPackageInfoAttributeValue& value)
415 return B_OK;
418 virtual void HandleErrorOccurred()
422 BString MakePath(const BPackageEntry* entry)
424 BString path;
425 while (entry != NULL) {
426 if (!path.IsEmpty())
427 path.Prepend('/', 1);
428 path.Prepend(entry->Name());
429 entry = entry->Parent();
431 return path;
434 private:
435 DeskbarLinkList& fDeskbarLinks;
439 class OpenPackageAction : public PackageAction {
440 public:
441 OpenPackageAction(PackageInfoRef package, Model* model,
442 const DeskbarLink& link)
444 PackageAction(PACKAGE_ACTION_OPEN, package, model),
445 fDeskbarLink(link),
446 fLabel(B_TRANSLATE("Open %DeskbarLink%"))
448 BString target = fDeskbarLink.link;
449 int32 lastPathSeparator = target.FindLast('/');
450 if (lastPathSeparator > 0 && lastPathSeparator + 1 < target.Length())
451 target.Remove(0, lastPathSeparator + 1);
453 fLabel.ReplaceAll("%DeskbarLink%", target);
456 virtual const char* Label() const
458 return fLabel;
461 virtual status_t Perform()
463 status_t status;
464 BPath path;
465 if (fDeskbarLink.link.FindFirst('/') == 0) {
466 status = path.SetTo(fDeskbarLink.link);
467 printf("trying to launch (absolute link): %s\n", path.Path());
468 } else {
469 int32 location = InstallLocation();
470 if (location == B_PACKAGE_INSTALLATION_LOCATION_SYSTEM) {
471 status = find_directory(B_SYSTEM_DIRECTORY, &path);
472 if (status != B_OK)
473 return status;
474 } else if (location == B_PACKAGE_INSTALLATION_LOCATION_HOME) {
475 status = find_directory(B_USER_DIRECTORY, &path);
476 if (status != B_OK)
477 return status;
478 } else {
479 return B_ERROR;
482 status = path.Append(fDeskbarLink.path);
483 if (status == B_OK)
484 status = path.GetParent(&path);
485 if (status == B_OK) {
486 status = path.Append(fDeskbarLink.link, true);
487 printf("trying to launch: %s\n", path.Path());
491 entry_ref ref;
492 if (status == B_OK)
493 status = get_ref_for_path(path.Path(), &ref);
495 if (status == B_OK)
496 status = be_roster->Launch(&ref);
498 return status;
501 static bool FindAppToLaunch(const PackageInfoRef& package,
502 DeskbarLinkList& foundLinks)
504 if (package.Get() == NULL)
505 return false;
507 int32 installLocation = InstallLocation(package);
509 BPath packagePath;
510 if (installLocation == B_PACKAGE_INSTALLATION_LOCATION_SYSTEM) {
511 if (find_directory(B_SYSTEM_PACKAGES_DIRECTORY, &packagePath)
512 != B_OK) {
513 return false;
515 } else if (installLocation == B_PACKAGE_INSTALLATION_LOCATION_HOME) {
516 if (find_directory(B_USER_PACKAGES_DIRECTORY, &packagePath)
517 != B_OK) {
518 return false;
520 } else {
521 printf("OpenPackageAction::FindAppToLaunch(): "
522 "unknown install location");
523 return false;
526 packagePath.Append(package->FileName());
528 BNoErrorOutput errorOutput;
529 BPackageReader reader(&errorOutput);
531 status_t status = reader.Init(packagePath.Path());
532 if (status != B_OK) {
533 printf("OpenPackageAction::FindAppToLaunch(): "
534 "failed to init BPackageReader(%s): %s\n",
535 packagePath.Path(), strerror(status));
536 return false;
539 // Scan package contents for Deskbar links
540 DeskbarLinkFinder contentHandler(foundLinks);
541 status = reader.ParseContent(&contentHandler);
542 if (status != B_OK) {
543 printf("OpenPackageAction::FindAppToLaunch(): "
544 "failed parse package contents (%s): %s\n",
545 packagePath.Path(), strerror(status));
546 return false;
549 return foundLinks.CountItems() > 0;
552 private:
553 DeskbarLink fDeskbarLink;
554 BString fLabel;
558 // #pragma mark - PackageManager
561 PackageManager::PackageManager(BPackageInstallationLocation location)
563 BPackageManager(location, &fClientInstallationInterface, this),
564 BPackageManager::UserInteractionHandler(),
565 fDecisionProvider(),
566 fClientInstallationInterface(),
567 fProblemWindow(NULL),
568 fCurrentInstallPackage(NULL),
569 fCurrentUninstallPackage(NULL)
574 PackageManager::~PackageManager()
576 if (fProblemWindow != NULL)
577 fProblemWindow->PostMessage(B_QUIT_REQUESTED);
581 PackageState
582 PackageManager::GetPackageState(const PackageInfo& package)
584 // TODO: Fetch information from the PackageKit
585 return NONE;
589 PackageActionList
590 PackageManager::GetPackageActions(PackageInfoRef package, Model* model)
592 PackageActionList actionList;
593 if (package->IsSystemPackage() || package->IsSystemDependency())
594 return actionList;
596 int32 state = package->State();
597 if (state == ACTIVATED || state == INSTALLED) {
598 actionList.Add(PackageActionRef(new UninstallPackageAction(
599 package, model), true));
601 // Add OpenPackageActions for each deskbar link found in the
602 // package
603 DeskbarLinkList foundLinks;
604 if (OpenPackageAction::FindAppToLaunch(package, foundLinks)
605 && foundLinks.CountItems() < 4) {
606 for (int32 i = 0; i < foundLinks.CountItems(); i++) {
607 const DeskbarLink& link = foundLinks.ItemAtFast(i);
608 actionList.Add(PackageActionRef(new OpenPackageAction(
609 package, model, link), true));
612 } else if (state == NONE || state == UNINSTALLED) {
613 actionList.Add(PackageActionRef(new InstallPackageAction(package,
614 model), true));
616 // TODO: activation status
618 return actionList;
622 void
623 PackageManager::SetCurrentActionPackage(PackageInfoRef package, bool install)
625 BSolverPackage* solverPackage = _GetSolverPackage(package);
626 fCurrentInstallPackage = install ? solverPackage : NULL;
627 fCurrentUninstallPackage = install ? NULL : solverPackage;
631 status_t
632 PackageManager::RefreshRepository(const BRepositoryConfig& repoConfig)
634 status_t result;
635 try {
636 result = BPackageManager::RefreshRepository(repoConfig);
637 } catch (BFatalErrorException ex) {
638 fprintf(stderr, "Fatal error occurred while refreshing repository: "
639 "%s (%s)\n", ex.Message().String(), ex.Details().String());
640 result = ex.Error();
641 } catch (BException ex) {
642 fprintf(stderr, "Exception occurred while refreshing "
643 "repository: %s\n", ex.Message().String());
644 result = B_ERROR;
647 return result;
651 status_t
652 PackageManager::DownloadPackage(const BString& fileURL,
653 const BEntry& targetEntry, const BString& checksum)
655 status_t result;
656 try {
657 result = BPackageManager::DownloadPackage(fileURL, targetEntry,
658 checksum);
659 } catch (BFatalErrorException ex) {
660 fprintf(stderr, "Fatal error occurred while downloading package: "
661 "%s: %s (%s)\n", fileURL.String(), ex.Message().String(),
662 ex.Details().String());
663 result = ex.Error();
664 } catch (BException ex) {
665 fprintf(stderr, "Exception occurred while downloading package "
666 "%s: %s\n", fileURL.String(), ex.Message().String());
667 result = B_ERROR;
670 return result;
674 void
675 PackageManager::AddProgressListener(PackageProgressListener* listener)
677 fPackageProgressListeners.AddItem(listener);
681 void
682 PackageManager::RemoveProgressListener(PackageProgressListener* listener)
684 fPackageProgressListeners.RemoveItem(listener);
688 void
689 PackageManager::HandleProblems()
691 if (fProblemWindow == NULL)
692 fProblemWindow = new ProblemWindow;
694 ProblemWindow::SolverPackageSet installPackages;
695 ProblemWindow::SolverPackageSet uninstallPackages;
696 if (fCurrentInstallPackage != NULL)
697 installPackages.insert(fCurrentInstallPackage);
699 if (fCurrentUninstallPackage != NULL)
700 uninstallPackages.insert(fCurrentUninstallPackage);
702 if (!fProblemWindow->Go(fSolver,installPackages, uninstallPackages))
703 throw BAbortedByUserException();
707 void
708 PackageManager::ConfirmChanges(bool fromMostSpecific)
710 ResultWindow* window = new ResultWindow;
711 ObjectDeleter<ResultWindow> windowDeleter(window);
713 bool hasOtherChanges = false;
714 int32 count = fInstalledRepositories.CountItems();
716 if (fromMostSpecific) {
717 for (int32 i = count - 1; i >= 0; i--)
718 hasOtherChanges
719 |= _AddResults(*fInstalledRepositories.ItemAt(i), window);
720 } else {
721 for (int32 i = 0; i < count; i++)
722 hasOtherChanges
723 |= _AddResults(*fInstalledRepositories.ItemAt(i), window);
726 if (!hasOtherChanges) {
727 _NotifyChangesConfirmed();
728 return;
731 // show the window
732 if (windowDeleter.Detach()->Go() == 0)
733 throw BAbortedByUserException();
735 _NotifyChangesConfirmed();
739 void
740 PackageManager::Warn(status_t error, const char* format, ...)
742 // TODO: Show alert to user
744 va_list args;
745 va_start(args, format);
746 vfprintf(stderr, format, args);
747 va_end(args);
749 if (error == B_OK)
750 printf("\n");
751 else
752 printf(": %s\n", strerror(error));
756 void
757 PackageManager::ProgressPackageDownloadStarted(const char* packageName)
759 ProgressPackageDownloadActive(packageName, 0.0f, 0, 0);
763 void
764 PackageManager::ProgressPackageDownloadActive(const char* packageName,
765 float completionPercentage, off_t bytes, off_t totalBytes)
767 for (int32 i = 0; i < fPackageProgressListeners.CountItems(); i++) {
768 fPackageProgressListeners.ItemAt(i)->DownloadProgressChanged(
769 packageName, completionPercentage);
774 void
775 PackageManager::ProgressPackageDownloadComplete(const char* packageName)
777 for (int32 i = 0; i < fPackageProgressListeners.CountItems(); i++) {
778 fPackageProgressListeners.ItemAt(i)->DownloadProgressComplete(
779 packageName);
784 void
785 PackageManager::ProgressPackageChecksumStarted(const char* title)
787 // TODO: implement
791 void
792 PackageManager::ProgressPackageChecksumComplete(const char* title)
794 // TODO: implement
798 void
799 PackageManager::ProgressStartApplyingChanges(InstalledRepository& repository)
801 for (int32 i = 0; i < fPackageProgressListeners.CountItems(); i++)
802 fPackageProgressListeners.ItemAt(i)->StartApplyingChanges(repository);
806 void
807 PackageManager::ProgressTransactionCommitted(InstalledRepository& repository,
808 const BCommitTransactionResult& result)
810 // TODO: implement
814 void
815 PackageManager::ProgressApplyingChangesDone(InstalledRepository& repository)
817 for (int32 i = 0; i < fPackageProgressListeners.CountItems(); i++)
818 fPackageProgressListeners.ItemAt(i)->ApplyingChangesDone(repository);
822 bool
823 PackageManager::_AddResults(InstalledRepository& repository,
824 ResultWindow* window)
826 if (!repository.HasChanges())
827 return false;
829 ProblemWindow::SolverPackageSet installPackages;
830 ProblemWindow::SolverPackageSet uninstallPackages;
831 if (fCurrentInstallPackage != NULL)
832 installPackages.insert(fCurrentInstallPackage);
834 if (fCurrentUninstallPackage != NULL)
835 uninstallPackages.insert(fCurrentUninstallPackage);
837 return window->AddLocationChanges(repository.Name(),
838 repository.PackagesToActivate(), installPackages,
839 repository.PackagesToDeactivate(), uninstallPackages);
843 void
844 PackageManager::_NotifyChangesConfirmed()
846 int32 count = fInstalledRepositories.CountItems();
847 for (int32 i = 0; i < count; i++) {
848 for (int32 j = 0; j < fPackageProgressListeners.CountItems(); j++) {
849 fPackageProgressListeners.ItemAt(j)->ConfirmedChanges(
850 *fInstalledRepositories.ItemAt(i));
856 BSolverPackage*
857 PackageManager::_GetSolverPackage(PackageInfoRef package)
859 int32 flags = BSolver::B_FIND_IN_NAME;
860 if (package->State() == ACTIVATED || package->State() == INSTALLED)
861 flags |= BSolver::B_FIND_INSTALLED_ONLY;
863 BObjectList<BSolverPackage> packages;
864 status_t result = Solver()->FindPackages(package->Name(), flags, packages);
865 if (result == B_OK) {
866 for (int32 i = 0; i < packages.CountItems(); i++) {
867 BSolverPackage* solverPackage = packages.ItemAt(i);
868 if (solverPackage->Name() != package->Name())
869 continue;
870 else if (package->State() == NONE
871 && dynamic_cast<BPackageManager::RemoteRepository*>(
872 solverPackage->Repository()) == NULL) {
873 continue;
875 return solverPackage;
879 return NULL;