xref: /haiku/src/servers/package/PackageManager.cpp (revision 38c62dfb8b5acffe9373b19e087d037d38a281a5)
1*38c62dfbSIngo Weinhold /*
2*38c62dfbSIngo Weinhold  * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3*38c62dfbSIngo Weinhold  * Distributed under the terms of the MIT License.
4*38c62dfbSIngo Weinhold  */
5*38c62dfbSIngo Weinhold 
6*38c62dfbSIngo Weinhold 
7*38c62dfbSIngo Weinhold #include "PackageManager.h"
8*38c62dfbSIngo Weinhold 
9*38c62dfbSIngo Weinhold #include <Alert.h>
10*38c62dfbSIngo Weinhold #include <Notification.h>
11*38c62dfbSIngo Weinhold #include <package/DownloadFileRequest.h>
12*38c62dfbSIngo Weinhold #include <package/RefreshRepositoryRequest.h>
13*38c62dfbSIngo Weinhold #include <package/solver/SolverPackage.h>
14*38c62dfbSIngo Weinhold #include <package/solver/SolverPackageSpecifierList.h>
15*38c62dfbSIngo Weinhold #include <package/solver/SolverProblem.h>
16*38c62dfbSIngo Weinhold #include <package/solver/SolverProblemSolution.h>
17*38c62dfbSIngo Weinhold 
18*38c62dfbSIngo Weinhold #include <package/manager/Exceptions.h>
19*38c62dfbSIngo Weinhold #include <package/manager/RepositoryBuilder.h>
20*38c62dfbSIngo Weinhold #include <Server.h>
21*38c62dfbSIngo Weinhold 
22*38c62dfbSIngo Weinhold #include "ProblemWindow.h"
23*38c62dfbSIngo Weinhold #include "Root.h"
24*38c62dfbSIngo Weinhold #include "Volume.h"
25*38c62dfbSIngo Weinhold 
26*38c62dfbSIngo Weinhold 
27*38c62dfbSIngo Weinhold using BPackageKit::BManager::BPrivate::BAbortedByUserException;
28*38c62dfbSIngo Weinhold using BPackageKit::BManager::BPrivate::BFatalErrorException;
29*38c62dfbSIngo Weinhold using BPackageKit::BManager::BPrivate::BRepositoryBuilder;
30*38c62dfbSIngo Weinhold 
31*38c62dfbSIngo Weinhold 
32*38c62dfbSIngo Weinhold PackageManager::PackageManager(Root* root, Volume* volume)
33*38c62dfbSIngo Weinhold 	:
34*38c62dfbSIngo Weinhold 	BPackageManager(volume->Location()),
35*38c62dfbSIngo Weinhold 	BPackageManager::UserInteractionHandler(),
36*38c62dfbSIngo Weinhold 	fRoot(root),
37*38c62dfbSIngo Weinhold 	fVolume(volume),
38*38c62dfbSIngo Weinhold 	fContext(*this, *this),
39*38c62dfbSIngo Weinhold 	fSolverPackages(),
40*38c62dfbSIngo Weinhold 	fPackagesAddedByUser(),
41*38c62dfbSIngo Weinhold 	fPackagesRemovedByUser(),
42*38c62dfbSIngo Weinhold 	fProblemWindow(NULL)
43*38c62dfbSIngo Weinhold {
44*38c62dfbSIngo Weinhold 	fInstallationInterface = this;
45*38c62dfbSIngo Weinhold 	fRequestHandler = this;
46*38c62dfbSIngo Weinhold 	fUserInteractionHandler = this;
47*38c62dfbSIngo Weinhold }
48*38c62dfbSIngo Weinhold 
49*38c62dfbSIngo Weinhold 
50*38c62dfbSIngo Weinhold PackageManager::~PackageManager()
51*38c62dfbSIngo Weinhold {
52*38c62dfbSIngo Weinhold 	if (fProblemWindow != NULL)
53*38c62dfbSIngo Weinhold 		fProblemWindow->PostMessage(B_QUIT_REQUESTED);
54*38c62dfbSIngo Weinhold }
55*38c62dfbSIngo Weinhold 
56*38c62dfbSIngo Weinhold 
57*38c62dfbSIngo Weinhold void
58*38c62dfbSIngo Weinhold PackageManager::HandleUserChanges()
59*38c62dfbSIngo Weinhold {
60*38c62dfbSIngo Weinhold 	const PackageSet& packagesToActivate = fVolume->PackagesToBeActivated();
61*38c62dfbSIngo Weinhold 	const PackageSet& packagesToDeactivate = fVolume->PackagesToBeDeactivated();
62*38c62dfbSIngo Weinhold 
63*38c62dfbSIngo Weinhold 	if (packagesToActivate.empty() && packagesToDeactivate.empty())
64*38c62dfbSIngo Weinhold 		return;
65*38c62dfbSIngo Weinhold 
66*38c62dfbSIngo Weinhold 	if (packagesToActivate.empty()) {
67*38c62dfbSIngo Weinhold 		// only packages removed -- use uninstall mode
68*38c62dfbSIngo Weinhold 		Init(B_ADD_INSTALLED_REPOSITORIES);
69*38c62dfbSIngo Weinhold 
70*38c62dfbSIngo Weinhold 		BSolverPackageSpecifierList packagesToUninstall;
71*38c62dfbSIngo Weinhold 		for (PackageSet::const_iterator it = packagesToDeactivate.begin();
72*38c62dfbSIngo Weinhold 			it != packagesToDeactivate.end(); ++it) {
73*38c62dfbSIngo Weinhold 			BSolverPackage* solverPackage = _SolverPackageFor(*it);
74*38c62dfbSIngo Weinhold 			if (solverPackage == NULL)
75*38c62dfbSIngo Weinhold 				continue;
76*38c62dfbSIngo Weinhold 
77*38c62dfbSIngo Weinhold 			if (!packagesToUninstall.AppendSpecifier(solverPackage))
78*38c62dfbSIngo Weinhold 				throw std::bad_alloc();
79*38c62dfbSIngo Weinhold 			fPackagesRemovedByUser.insert(solverPackage);
80*38c62dfbSIngo Weinhold 		}
81*38c62dfbSIngo Weinhold 
82*38c62dfbSIngo Weinhold 		if (fPackagesRemovedByUser.empty())
83*38c62dfbSIngo Weinhold 			return;
84*38c62dfbSIngo Weinhold 
85*38c62dfbSIngo Weinhold 		Uninstall(packagesToUninstall);
86*38c62dfbSIngo Weinhold 	} else {
87*38c62dfbSIngo Weinhold 		// packages added and (possibly) remove -- manually add/remove those
88*38c62dfbSIngo Weinhold 		// from the repository and use verify mode
89*38c62dfbSIngo Weinhold 		Init(B_ADD_INSTALLED_REPOSITORIES | B_ADD_REMOTE_REPOSITORIES
90*38c62dfbSIngo Weinhold 			| B_REFRESH_REPOSITORIES);
91*38c62dfbSIngo Weinhold 
92*38c62dfbSIngo Weinhold 		// disable and remove uninstalled packages
93*38c62dfbSIngo Weinhold 		InstalledRepository& repository = InstallationRepository();
94*38c62dfbSIngo Weinhold 		for (PackageSet::const_iterator it = packagesToDeactivate.begin();
95*38c62dfbSIngo Weinhold 			it != packagesToDeactivate.end(); ++it) {
96*38c62dfbSIngo Weinhold 			BSolverPackage* solverPackage = _SolverPackageFor(*it);
97*38c62dfbSIngo Weinhold 			if (solverPackage == NULL)
98*38c62dfbSIngo Weinhold 				continue;
99*38c62dfbSIngo Weinhold 
100*38c62dfbSIngo Weinhold 			repository.DisablePackage(solverPackage);
101*38c62dfbSIngo Weinhold 			if (!repository.PackagesToDeactivate().AddItem(solverPackage))
102*38c62dfbSIngo Weinhold 				throw std::bad_alloc();
103*38c62dfbSIngo Weinhold 			fPackagesRemovedByUser.insert(solverPackage);
104*38c62dfbSIngo Weinhold 		}
105*38c62dfbSIngo Weinhold 
106*38c62dfbSIngo Weinhold 		// add new packages
107*38c62dfbSIngo Weinhold 		BRepositoryBuilder repositoryBuilder(repository);
108*38c62dfbSIngo Weinhold 		for (PackageSet::const_iterator it = packagesToActivate.begin();
109*38c62dfbSIngo Weinhold 			it != packagesToActivate.end(); ++it) {
110*38c62dfbSIngo Weinhold 			Package* package = *it;
111*38c62dfbSIngo Weinhold 			BSolverPackage* solverPackage;
112*38c62dfbSIngo Weinhold 			repositoryBuilder.AddPackage(package->Info(), NULL, &solverPackage);
113*38c62dfbSIngo Weinhold 			fSolverPackages[package] = solverPackage;
114*38c62dfbSIngo Weinhold 			if (!repository.PackagesToActivate().AddItem(solverPackage))
115*38c62dfbSIngo Weinhold 				throw std::bad_alloc();
116*38c62dfbSIngo Weinhold 			fPackagesAddedByUser.insert(solverPackage);
117*38c62dfbSIngo Weinhold 		}
118*38c62dfbSIngo Weinhold 
119*38c62dfbSIngo Weinhold 		if (fPackagesRemovedByUser.empty() && fPackagesAddedByUser.empty())
120*38c62dfbSIngo Weinhold 			return;
121*38c62dfbSIngo Weinhold 
122*38c62dfbSIngo Weinhold // TODO: When packages are moved out of the packages directory, we can't create
123*38c62dfbSIngo Weinhold // a complete "old-state" directory.
124*38c62dfbSIngo Weinhold 
125*38c62dfbSIngo Weinhold 		VerifyInstallation();
126*38c62dfbSIngo Weinhold 	}
127*38c62dfbSIngo Weinhold }
128*38c62dfbSIngo Weinhold 
129*38c62dfbSIngo Weinhold 
130*38c62dfbSIngo Weinhold void
131*38c62dfbSIngo Weinhold PackageManager::InitInstalledRepository(InstalledRepository& repository)
132*38c62dfbSIngo Weinhold {
133*38c62dfbSIngo Weinhold 	const char* name = repository.InitialName();
134*38c62dfbSIngo Weinhold 	BRepositoryBuilder repositoryBuilder(repository, name);
135*38c62dfbSIngo Weinhold 
136*38c62dfbSIngo Weinhold 	if (Volume* volume = fRoot->GetVolume(repository.Location())) {
137*38c62dfbSIngo Weinhold 		for (PackageFileNameHashTable::Iterator it
138*38c62dfbSIngo Weinhold 				= volume->PackagesByFileName().GetIterator(); it.HasNext();) {
139*38c62dfbSIngo Weinhold 			Package* package = it.Next();
140*38c62dfbSIngo Weinhold 			if (package->IsActive()) {
141*38c62dfbSIngo Weinhold 				BSolverPackage* solverPackage;
142*38c62dfbSIngo Weinhold 				repositoryBuilder.AddPackage(package->Info(), NULL,
143*38c62dfbSIngo Weinhold 					&solverPackage);
144*38c62dfbSIngo Weinhold 				fSolverPackages[package] = solverPackage;
145*38c62dfbSIngo Weinhold 			}
146*38c62dfbSIngo Weinhold 		}
147*38c62dfbSIngo Weinhold 	}
148*38c62dfbSIngo Weinhold }
149*38c62dfbSIngo Weinhold 
150*38c62dfbSIngo Weinhold 
151*38c62dfbSIngo Weinhold void
152*38c62dfbSIngo Weinhold PackageManager::ResultComputed(InstalledRepository& repository)
153*38c62dfbSIngo Weinhold {
154*38c62dfbSIngo Weinhold 	// Normalize the result, i.e. remove the packages added by the user which
155*38c62dfbSIngo Weinhold 	// have been removed again in the problem resolution process, and vice
156*38c62dfbSIngo Weinhold 	// versa.
157*38c62dfbSIngo Weinhold 	if (repository.Location() != fVolume->Location())
158*38c62dfbSIngo Weinhold 		return;
159*38c62dfbSIngo Weinhold 
160*38c62dfbSIngo Weinhold 	PackageList& packagesToActivate = repository.PackagesToActivate();
161*38c62dfbSIngo Weinhold 	PackageList& packagesToDeactivate = repository.PackagesToDeactivate();
162*38c62dfbSIngo Weinhold 
163*38c62dfbSIngo Weinhold 	for (int32 i = 0; BSolverPackage* package = packagesToDeactivate.ItemAt(i);
164*38c62dfbSIngo Weinhold 		i++) {
165*38c62dfbSIngo Weinhold 		if (fPackagesAddedByUser.erase(package) == 0)
166*38c62dfbSIngo Weinhold 			continue;
167*38c62dfbSIngo Weinhold 
168*38c62dfbSIngo Weinhold 		for (SolverPackageMap::iterator it = fSolverPackages.begin();
169*38c62dfbSIngo Weinhold 			it != fSolverPackages.end(); ++it) {
170*38c62dfbSIngo Weinhold 			if (it->second == package) {
171*38c62dfbSIngo Weinhold 				fSolverPackages.erase(it);
172*38c62dfbSIngo Weinhold 				break;
173*38c62dfbSIngo Weinhold 			}
174*38c62dfbSIngo Weinhold 		}
175*38c62dfbSIngo Weinhold 
176*38c62dfbSIngo Weinhold 		repository.EnablePackage(package);
177*38c62dfbSIngo Weinhold 		packagesToDeactivate.RemoveItemAt(i--);
178*38c62dfbSIngo Weinhold 		packagesToActivate.RemoveItem(package);
179*38c62dfbSIngo Weinhold 		repository.DeletePackage(package);
180*38c62dfbSIngo Weinhold 	}
181*38c62dfbSIngo Weinhold 
182*38c62dfbSIngo Weinhold 	for (int32 i = 0; BSolverPackage* package = packagesToActivate.ItemAt(i);
183*38c62dfbSIngo Weinhold 		i++) {
184*38c62dfbSIngo Weinhold 		if (fPackagesRemovedByUser.erase(package) == 0)
185*38c62dfbSIngo Weinhold 			continue;
186*38c62dfbSIngo Weinhold 
187*38c62dfbSIngo Weinhold 		repository.EnablePackage(package);
188*38c62dfbSIngo Weinhold 		packagesToActivate.RemoveItemAt(i--);
189*38c62dfbSIngo Weinhold 		packagesToDeactivate.RemoveItem(package);
190*38c62dfbSIngo Weinhold 
191*38c62dfbSIngo Weinhold 		// Note: We keep the package activated, but nonetheless it is gone,
192*38c62dfbSIngo Weinhold 		// since the user has removed it from the packages directory. So unless
193*38c62dfbSIngo Weinhold 		// the user moves it back, we won't find it upon next reboot.
194*38c62dfbSIngo Weinhold 		// TODO: We probable even run into trouble when the user moves in a
195*38c62dfbSIngo Weinhold 		// replacement afterward.
196*38c62dfbSIngo Weinhold 	}
197*38c62dfbSIngo Weinhold }
198*38c62dfbSIngo Weinhold 
199*38c62dfbSIngo Weinhold 
200*38c62dfbSIngo Weinhold status_t
201*38c62dfbSIngo Weinhold PackageManager::PrepareTransaction(Transaction& transaction)
202*38c62dfbSIngo Weinhold {
203*38c62dfbSIngo Weinhold 	Volume* volume = fRoot->GetVolume(transaction.Repository().Location());
204*38c62dfbSIngo Weinhold 	if (volume == NULL)
205*38c62dfbSIngo Weinhold 		return B_BAD_VALUE;
206*38c62dfbSIngo Weinhold 
207*38c62dfbSIngo Weinhold 	return volume->CreateTransaction(transaction.Repository().Location(),
208*38c62dfbSIngo Weinhold 		transaction.ActivationTransaction(),
209*38c62dfbSIngo Weinhold 		transaction.TransactionDirectory());
210*38c62dfbSIngo Weinhold }
211*38c62dfbSIngo Weinhold 
212*38c62dfbSIngo Weinhold 
213*38c62dfbSIngo Weinhold status_t
214*38c62dfbSIngo Weinhold PackageManager::CommitTransaction(Transaction& transaction,
215*38c62dfbSIngo Weinhold 	BDaemonClient::BCommitTransactionResult& _result)
216*38c62dfbSIngo Weinhold {
217*38c62dfbSIngo Weinhold debug_printf("PackageManager::CommitTransaction()\n");
218*38c62dfbSIngo Weinhold 	Volume* volume = fRoot->GetVolume(transaction.Repository().Location());
219*38c62dfbSIngo Weinhold 	if (volume == NULL)
220*38c62dfbSIngo Weinhold 		return B_BAD_VALUE;
221*38c62dfbSIngo Weinhold 
222*38c62dfbSIngo Weinhold 	// Get the packages that have already been added to/removed from the
223*38c62dfbSIngo Weinhold 	// packages directory and thus need to be handled specially by
224*38c62dfbSIngo Weinhold 	// Volume::CommitTransaction().
225*38c62dfbSIngo Weinhold 	PackageSet packagesAlreadyAdded;
226*38c62dfbSIngo Weinhold 	PackageSet packagesAlreadyRemoved;
227*38c62dfbSIngo Weinhold 	if (volume == fVolume) {
228*38c62dfbSIngo Weinhold 		const PackageSet& packagesToActivate = volume->PackagesToBeActivated();
229*38c62dfbSIngo Weinhold 		for (PackageSet::const_iterator it = packagesToActivate.begin();
230*38c62dfbSIngo Weinhold 			it != packagesToActivate.end(); ++it) {
231*38c62dfbSIngo Weinhold 			Package* package = *it;
232*38c62dfbSIngo Weinhold 			if (fPackagesAddedByUser.find(_SolverPackageFor(package))
233*38c62dfbSIngo Weinhold 					!= fPackagesAddedByUser.end()) {
234*38c62dfbSIngo Weinhold 				packagesAlreadyAdded.insert(package);
235*38c62dfbSIngo Weinhold 			}
236*38c62dfbSIngo Weinhold 		}
237*38c62dfbSIngo Weinhold 
238*38c62dfbSIngo Weinhold 		const PackageSet& packagesToDeactivate
239*38c62dfbSIngo Weinhold 			= volume->PackagesToBeDeactivated();
240*38c62dfbSIngo Weinhold 		for (PackageSet::const_iterator it = packagesToDeactivate.begin();
241*38c62dfbSIngo Weinhold 			it != packagesToDeactivate.end(); ++it) {
242*38c62dfbSIngo Weinhold 			Package* package = *it;
243*38c62dfbSIngo Weinhold 			if (fPackagesRemovedByUser.find(_SolverPackageFor(package))
244*38c62dfbSIngo Weinhold 					!= fPackagesRemovedByUser.end()) {
245*38c62dfbSIngo Weinhold 				packagesAlreadyRemoved.insert(package);
246*38c62dfbSIngo Weinhold 			}
247*38c62dfbSIngo Weinhold 		}
248*38c62dfbSIngo Weinhold 	}
249*38c62dfbSIngo Weinhold debug_printf("  activating   %ld (%zu) packages\n", transaction.ActivationTransaction().PackagesToActivate().CountStrings(), packagesAlreadyAdded.size());
250*38c62dfbSIngo Weinhold debug_printf("  deactivating %ld (%zu) packages\n", transaction.ActivationTransaction().PackagesToDeactivate().CountStrings(), packagesAlreadyRemoved.size());
251*38c62dfbSIngo Weinhold 
252*38c62dfbSIngo Weinhold 	volume->CommitTransaction(transaction.ActivationTransaction(),
253*38c62dfbSIngo Weinhold 		packagesAlreadyAdded, packagesAlreadyRemoved, _result);
254*38c62dfbSIngo Weinhold 	return B_OK;
255*38c62dfbSIngo Weinhold }
256*38c62dfbSIngo Weinhold 
257*38c62dfbSIngo Weinhold 
258*38c62dfbSIngo Weinhold status_t
259*38c62dfbSIngo Weinhold PackageManager::RefreshRepository(const BRepositoryConfig& repoConfig)
260*38c62dfbSIngo Weinhold {
261*38c62dfbSIngo Weinhold 	return BRefreshRepositoryRequest(fContext, repoConfig).Process();
262*38c62dfbSIngo Weinhold }
263*38c62dfbSIngo Weinhold 
264*38c62dfbSIngo Weinhold 
265*38c62dfbSIngo Weinhold status_t
266*38c62dfbSIngo Weinhold PackageManager::DownloadPackage(const BString& fileURL,
267*38c62dfbSIngo Weinhold 	const BEntry& targetEntry, const BString& checksum)
268*38c62dfbSIngo Weinhold {
269*38c62dfbSIngo Weinhold 	return DownloadFileRequest(fContext, fileURL, targetEntry, checksum)
270*38c62dfbSIngo Weinhold 		.Process();
271*38c62dfbSIngo Weinhold }
272*38c62dfbSIngo Weinhold 
273*38c62dfbSIngo Weinhold 
274*38c62dfbSIngo Weinhold void
275*38c62dfbSIngo Weinhold PackageManager::HandleProblems()
276*38c62dfbSIngo Weinhold {
277*38c62dfbSIngo Weinhold 	_InitGui();
278*38c62dfbSIngo Weinhold 
279*38c62dfbSIngo Weinhold 	if (fProblemWindow == NULL)
280*38c62dfbSIngo Weinhold 		fProblemWindow = new ProblemWindow;
281*38c62dfbSIngo Weinhold 
282*38c62dfbSIngo Weinhold 	if (!fProblemWindow->Go(fSolver, fPackagesAddedByUser,
283*38c62dfbSIngo Weinhold 			fPackagesRemovedByUser)) {
284*38c62dfbSIngo Weinhold 		throw BAbortedByUserException();
285*38c62dfbSIngo Weinhold 	}
286*38c62dfbSIngo Weinhold }
287*38c62dfbSIngo Weinhold 
288*38c62dfbSIngo Weinhold 
289*38c62dfbSIngo Weinhold void
290*38c62dfbSIngo Weinhold PackageManager::ConfirmChanges(bool fromMostSpecific)
291*38c62dfbSIngo Weinhold {
292*38c62dfbSIngo Weinhold 	// Check whether there are any changes other than those made by the user.
293*38c62dfbSIngo Weinhold 	BString alertText(
294*38c62dfbSIngo Weinhold 		"The following additional package changes have to be made:");
295*38c62dfbSIngo Weinhold 	bool hasOtherChanges = false;
296*38c62dfbSIngo Weinhold 	int32 count = fInstalledRepositories.CountItems();
297*38c62dfbSIngo Weinhold 	if (fromMostSpecific) {
298*38c62dfbSIngo Weinhold 		for (int32 i = count - 1; i >= 0; i--)
299*38c62dfbSIngo Weinhold 			hasOtherChanges
300*38c62dfbSIngo Weinhold 				|= _GetResultText(*fInstalledRepositories.ItemAt(i), alertText);
301*38c62dfbSIngo Weinhold 	} else {
302*38c62dfbSIngo Weinhold 		for (int32 i = 0; i < count; i++)
303*38c62dfbSIngo Weinhold 			hasOtherChanges
304*38c62dfbSIngo Weinhold 				|= _GetResultText(*fInstalledRepositories.ItemAt(i), alertText);
305*38c62dfbSIngo Weinhold 	}
306*38c62dfbSIngo Weinhold 
307*38c62dfbSIngo Weinhold 	if (!hasOtherChanges)
308*38c62dfbSIngo Weinhold 		return;
309*38c62dfbSIngo Weinhold 
310*38c62dfbSIngo Weinhold 	// show an alert
311*38c62dfbSIngo Weinhold 	_InitGui();
312*38c62dfbSIngo Weinhold 	BAlert* alert = new BAlert("Package changes", alertText,
313*38c62dfbSIngo Weinhold        "Cancel", "Apply changes");
314*38c62dfbSIngo Weinhold 	alert->SetShortcut(0, B_ESCAPE);
315*38c62dfbSIngo Weinhold 	if (alert->Go() == 0)
316*38c62dfbSIngo Weinhold 		throw BAbortedByUserException();
317*38c62dfbSIngo Weinhold }
318*38c62dfbSIngo Weinhold 
319*38c62dfbSIngo Weinhold 
320*38c62dfbSIngo Weinhold void
321*38c62dfbSIngo Weinhold PackageManager::Warn(status_t error, const char* format, ...)
322*38c62dfbSIngo Weinhold {
323*38c62dfbSIngo Weinhold 	va_list args;
324*38c62dfbSIngo Weinhold 	va_start(args, format);
325*38c62dfbSIngo Weinhold 	BString message;
326*38c62dfbSIngo Weinhold 	message.SetToFormatVarArgs(format, args);
327*38c62dfbSIngo Weinhold 	va_end(args);
328*38c62dfbSIngo Weinhold 
329*38c62dfbSIngo Weinhold 	if (error != B_OK)
330*38c62dfbSIngo Weinhold 		message << BString().SetToFormat(": %s", strerror(error));
331*38c62dfbSIngo Weinhold 
332*38c62dfbSIngo Weinhold 	BNotification notification(B_ERROR_NOTIFICATION);
333*38c62dfbSIngo Weinhold 	notification.SetTitle("Package Daemon");
334*38c62dfbSIngo Weinhold 	notification.SetContent(message);
335*38c62dfbSIngo Weinhold 	notification.Send();
336*38c62dfbSIngo Weinhold }
337*38c62dfbSIngo Weinhold 
338*38c62dfbSIngo Weinhold 
339*38c62dfbSIngo Weinhold void
340*38c62dfbSIngo Weinhold PackageManager::ProgressStartApplyingChanges(InstalledRepository& repository)
341*38c62dfbSIngo Weinhold {
342*38c62dfbSIngo Weinhold }
343*38c62dfbSIngo Weinhold 
344*38c62dfbSIngo Weinhold 
345*38c62dfbSIngo Weinhold void
346*38c62dfbSIngo Weinhold PackageManager::ProgressTransactionCommitted(InstalledRepository& repository,
347*38c62dfbSIngo Weinhold 	const char* transactionDirectoryName)
348*38c62dfbSIngo Weinhold {
349*38c62dfbSIngo Weinhold }
350*38c62dfbSIngo Weinhold 
351*38c62dfbSIngo Weinhold 
352*38c62dfbSIngo Weinhold void
353*38c62dfbSIngo Weinhold PackageManager::ProgressApplyingChangesDone(InstalledRepository& repository)
354*38c62dfbSIngo Weinhold {
355*38c62dfbSIngo Weinhold }
356*38c62dfbSIngo Weinhold 
357*38c62dfbSIngo Weinhold 
358*38c62dfbSIngo Weinhold bool
359*38c62dfbSIngo Weinhold PackageManager::YesNoDecisionNeeded(const BString& description,
360*38c62dfbSIngo Weinhold 	const BString& question, const BString& yes, const BString& no,
361*38c62dfbSIngo Weinhold 	const BString& defaultChoice)
362*38c62dfbSIngo Weinhold {
363*38c62dfbSIngo Weinhold 	// ATM we need the BDecisionProvider object for the BContext, but we don't
364*38c62dfbSIngo Weinhold 	// execute any request which actually uses it.
365*38c62dfbSIngo Weinhold 	return false;
366*38c62dfbSIngo Weinhold }
367*38c62dfbSIngo Weinhold 
368*38c62dfbSIngo Weinhold 
369*38c62dfbSIngo Weinhold void
370*38c62dfbSIngo Weinhold PackageManager::JobFailed(BJob* job)
371*38c62dfbSIngo Weinhold {
372*38c62dfbSIngo Weinhold // TODO:...
373*38c62dfbSIngo Weinhold }
374*38c62dfbSIngo Weinhold 
375*38c62dfbSIngo Weinhold 
376*38c62dfbSIngo Weinhold void
377*38c62dfbSIngo Weinhold PackageManager::JobAborted(BJob* job)
378*38c62dfbSIngo Weinhold {
379*38c62dfbSIngo Weinhold // TODO:...
380*38c62dfbSIngo Weinhold }
381*38c62dfbSIngo Weinhold 
382*38c62dfbSIngo Weinhold 
383*38c62dfbSIngo Weinhold bool
384*38c62dfbSIngo Weinhold PackageManager::_GetResultText(InstalledRepository& repository,
385*38c62dfbSIngo Weinhold 	BString& _text)
386*38c62dfbSIngo Weinhold {
387*38c62dfbSIngo Weinhold 	if (!repository.HasChanges())
388*38c62dfbSIngo Weinhold 		return false;
389*38c62dfbSIngo Weinhold 
390*38c62dfbSIngo Weinhold 	bool hasOtherChanges = false;
391*38c62dfbSIngo Weinhold 	bool isTargetLocation
392*38c62dfbSIngo Weinhold 		= repository.Location() == fVolume->Location();
393*38c62dfbSIngo Weinhold 
394*38c62dfbSIngo Weinhold 	BString text = BString().SetToFormat("\n  in %s:",
395*38c62dfbSIngo Weinhold 		repository.Name().String());
396*38c62dfbSIngo Weinhold 
397*38c62dfbSIngo Weinhold 	PackageList& packagesToActivate = repository.PackagesToActivate();
398*38c62dfbSIngo Weinhold 	PackageList& packagesToDeactivate = repository.PackagesToDeactivate();
399*38c62dfbSIngo Weinhold 
400*38c62dfbSIngo Weinhold 	for (int32 i = 0; BSolverPackage* package = packagesToActivate.ItemAt(i);
401*38c62dfbSIngo Weinhold 		i++) {
402*38c62dfbSIngo Weinhold 		if (isTargetLocation
403*38c62dfbSIngo Weinhold 			&& fPackagesAddedByUser.find(package)
404*38c62dfbSIngo Weinhold 				!= fPackagesAddedByUser.end()) {
405*38c62dfbSIngo Weinhold 			continue;
406*38c62dfbSIngo Weinhold 		}
407*38c62dfbSIngo Weinhold 
408*38c62dfbSIngo Weinhold 		text << BString().SetToFormat(
409*38c62dfbSIngo Weinhold 			"\n    install package %s from repository %s\n",
410*38c62dfbSIngo Weinhold 			package->Info().FileName().String(),
411*38c62dfbSIngo Weinhold 			package->Repository()->Name().String());
412*38c62dfbSIngo Weinhold 		hasOtherChanges = true;
413*38c62dfbSIngo Weinhold 	}
414*38c62dfbSIngo Weinhold 
415*38c62dfbSIngo Weinhold 	for (int32 i = 0; BSolverPackage* package = packagesToDeactivate.ItemAt(i);
416*38c62dfbSIngo Weinhold 		i++) {
417*38c62dfbSIngo Weinhold 		if (isTargetLocation
418*38c62dfbSIngo Weinhold 			&& fPackagesRemovedByUser.find(package)
419*38c62dfbSIngo Weinhold 				!= fPackagesRemovedByUser.end()) {
420*38c62dfbSIngo Weinhold 			continue;
421*38c62dfbSIngo Weinhold 		}
422*38c62dfbSIngo Weinhold 
423*38c62dfbSIngo Weinhold 		text << BString().SetToFormat(
424*38c62dfbSIngo Weinhold 			"\n    uninstall package %s\n", package->VersionedName().String());
425*38c62dfbSIngo Weinhold 		hasOtherChanges = true;
426*38c62dfbSIngo Weinhold 	}
427*38c62dfbSIngo Weinhold 
428*38c62dfbSIngo Weinhold 	if (!hasOtherChanges)
429*38c62dfbSIngo Weinhold 		return false;
430*38c62dfbSIngo Weinhold 
431*38c62dfbSIngo Weinhold 	_text << text;
432*38c62dfbSIngo Weinhold 	return true;
433*38c62dfbSIngo Weinhold }
434*38c62dfbSIngo Weinhold 
435*38c62dfbSIngo Weinhold 
436*38c62dfbSIngo Weinhold BSolverPackage*
437*38c62dfbSIngo Weinhold PackageManager::_SolverPackageFor(Package* package) const
438*38c62dfbSIngo Weinhold {
439*38c62dfbSIngo Weinhold 	SolverPackageMap::const_iterator it = fSolverPackages.find(package);
440*38c62dfbSIngo Weinhold 	return it != fSolverPackages.end() ? it->second : NULL;
441*38c62dfbSIngo Weinhold }
442*38c62dfbSIngo Weinhold 
443*38c62dfbSIngo Weinhold 
444*38c62dfbSIngo Weinhold void
445*38c62dfbSIngo Weinhold PackageManager::_InitGui()
446*38c62dfbSIngo Weinhold {
447*38c62dfbSIngo Weinhold 	BServer* server = dynamic_cast<BServer*>(be_app);
448*38c62dfbSIngo Weinhold 	if (server == NULL || server->InitGUIContext() != B_OK)
449*38c62dfbSIngo Weinhold 		throw BFatalErrorException("failed to initialize the GUI");
450*38c62dfbSIngo Weinhold }
451