2 * Copyright 2013-2017, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Axel Dörfler <axeld@pinc-software.de>
7 * Rene Gollent <rene@gollent.com>
8 * Ingo Weinhold <ingo_weinhold@gmx.de>
9 * Brian Hill <supernova@tycho.email>
13 #include "CheckManager.h"
15 #include <sys/ioctl.h>
18 #include <Application.h>
21 #include <Messenger.h>
22 #include <NetworkInterface.h>
23 #include <NetworkRoster.h>
25 #include <Notification.h>
28 #include <package/manager/Exceptions.h>
29 #include <package/solver/SolverPackage.h>
30 #include <package/solver/SolverProblem.h>
31 #include <package/solver/SolverProblemSolution.h>
33 #include "constants.h"
35 using namespace BPackageKit
;
36 using namespace BPackageKit::BManager::BPrivate
;
38 #undef B_TRANSLATION_CONTEXT
39 #define B_TRANSLATION_CONTEXT "CheckManager"
42 CheckManager::CheckManager(BPackageInstallationLocation location
,
45 BPackageManager(location
, &fClientInstallationInterface
, this),
46 BPackageManager::UserInteractionHandler(),
47 fClientInstallationInterface(),
53 if (be_app
->GetAppInfo(&info
)!= B_OK
)
56 fNotificationId
<< info
.team
;
58 fHeaderChecking
= B_TRANSLATE("Checking for updates");
59 fTextContacting
= B_TRANSLATE("Contacting software repositories to check "
60 "for package updates.");
65 CheckManager::CheckNetworkConnection()
67 BNetworkRoster
& roster
= BNetworkRoster::Default();
68 BNetworkInterface interface
;
70 while (roster
.GetNextInterface(&cookie
, interface
) == B_OK
) {
71 uint32 flags
= interface
.Flags();
72 if ((flags
& IFF_LOOPBACK
) == 0
73 && (flags
& (IFF_UP
| IFF_LINK
)) == (IFF_UP
| IFF_LINK
)) {
78 // No network connection detected, cannot continue
79 fputs(B_TRANSLATE("No active network connection was found.\n"), stderr
);
80 throw BAbortedByUserException();
85 CheckManager::JobFailed(BSupportKit::BJob
* job
)
87 BString error
= job
->ErrorString();
88 if (error
.Length() > 0) {
89 error
.ReplaceAll("\n", "\n*** ");
90 fprintf(stderr
, "%s", error
.String());
96 CheckManager::JobAborted(BSupportKit::BJob
* job
)
99 BString error
= job
->ErrorString();
100 if (error
.Length() > 0) {
101 error
.ReplaceAll("\n", "\n*** ");
102 fprintf(stderr
, "%s", error
.String());
108 CheckManager::NoUpdatesNotification()
111 BString header
= B_TRANSLATE("No updates available");
112 BString text
= B_TRANSLATE("There were no updates found.");
113 _SendNotification(header
.String(), text
.String());
119 CheckManager::HandleProblems()
121 puts("Encountered problems:");
123 int32 problemCount
= fSolver
->CountProblems();
124 for (int32 i
= 0; i
< problemCount
; i
++) {
125 BSolverProblem
* problem
= fSolver
->ProblemAt(i
);
126 printf("problem %" B_PRId32
": %s\n", i
+ 1,
127 problem
->ToString().String());
130 BString
title(B_TRANSLATE("Available updates found"));
131 BString
text(B_TRANSLATE("Click here to run SoftwareUpdater. Some updates "
132 "will require a problem solution to be selected."));
133 _SendNotification(title
, text
);
135 throw BAbortedByUserException();
140 CheckManager::ConfirmChanges(bool fromMostSpecific
)
142 int32 count
= fInstalledRepositories
.CountItems();
143 int32 updateCount
= 0;
145 if (fromMostSpecific
) {
146 for (int32 i
= count
- 1; i
>= 0; i
--)
147 _CountUpdates(*fInstalledRepositories
.ItemAt(i
), updateCount
);
149 for (int32 i
= 0; i
< count
; i
++)
150 _CountUpdates(*fInstalledRepositories
.ItemAt(i
), updateCount
);
153 printf("Update count=%" B_PRId32
"\n", updateCount
);
154 if (updateCount
> 0) {
155 BString
title(B_TRANSLATE("%count% packages have available updates"));
157 count
<< updateCount
;
158 title
.ReplaceFirst("%count%", count
);
159 BString
text(B_TRANSLATE("Click here to install updates."));
160 _SendNotification(title
.String(), text
.String());
162 throw BAbortedByUserException();
167 CheckManager::Warn(status_t error
, const char* format
, ...)
170 va_start(args
, format
);
171 vfprintf(stderr
, format
, args
);
177 printf(": %s\n", strerror(error
));
182 CheckManager::ProgressPackageDownloadStarted(const char* packageName
)
185 _SendNotification(fHeaderChecking
.String(), fTextContacting
.String());
187 printf("Downloading %s...\n", packageName
);
192 CheckManager::ProgressPackageDownloadActive(const char* packageName
,
193 float completionPercentage
, off_t bytes
, off_t totalBytes
)
195 static const char* progressChars
[] = {
208 struct winsize winSize
;
209 if (ioctl(STDOUT_FILENO
, TIOCGWINSZ
, &winSize
) == 0
210 && winSize
.ws_col
< 77) {
211 // We need 7 characters for the percent display
212 width
= winSize
.ws_col
- 7;
216 int ipart
= (int)(completionPercentage
* width
);
217 int fpart
= (int)(((completionPercentage
* width
) - ipart
) * 8);
219 fputs("\r", stdout
); // return to the beginning of the line
221 for (position
= 0; position
< width
; position
++) {
222 if (position
< ipart
) {
223 // This part is fully downloaded, show a full block
224 fputs(progressChars
[7], stdout
);
225 } else if (position
> ipart
) {
226 // This part is not downloaded, show a space
229 // This part is partially downloaded
230 fputs(progressChars
[fpart
], stdout
);
234 // Also print the progress percentage
235 printf(" %3d%%", (int)(completionPercentage
* 100));
243 CheckManager::ProgressPackageDownloadComplete(const char* packageName
)
245 // Overwrite the progress bar with whitespace
248 ioctl(STDOUT_FILENO
, TIOCGWINSZ
, &w
);
249 for (int i
= 0; i
< (w
.ws_col
); i
++)
251 fputs("\r\x1b[1A", stdout
); // Go to previous line.
253 printf("Downloading %s...done.\n", packageName
);
258 CheckManager::ProgressPackageChecksumStarted(const char* title
)
261 _SendNotification(fHeaderChecking
.String(), title
);
263 printf("%s...", title
);
268 CheckManager::ProgressPackageChecksumComplete(const char* title
)
275 CheckManager::_CountUpdates(InstalledRepository
& installationRepository
,
278 if (!installationRepository
.HasChanges())
281 PackageList
& packagesToActivate
282 = installationRepository
.PackagesToActivate();
283 PackageList
& packagesToDeactivate
284 = installationRepository
.PackagesToDeactivate();
287 BSolverPackage
* installPackage
= packagesToActivate
.ItemAt(i
);
290 BSolverPackage
* uninstallPackage
= packagesToDeactivate
.ItemAt(j
);
292 if (installPackage
->Info().Name() == uninstallPackage
->Info().Name()) {
302 CheckManager::_SendNotification(const char* title
, const char* text
)
304 BNotification
notification(B_INFORMATION_NOTIFICATION
);
305 notification
.SetGroup("SoftwareUpdater");
306 notification
.SetTitle(title
);
307 notification
.SetContent(text
);
308 notification
.SetOnClickApp(kAppSignature
);
310 notification
.SetMessageID(fNotificationId
);