1
1
/*
2
- * Copyright (C) 2013-2018 Jolla Ltd.
2
+ * Copyright (c) 2013 – 2019 Jolla Ltd.
3
+ * Copyright (c) 2019 Open Mobile Platform LLC.
3
4
* Contact: Thomas Perl <[email protected] >
4
5
* Contact: Raine Makelainen <[email protected] >
5
6
*
55
56
/* A file that is provided by the developer mode package */
56
57
#define DEVELOPER_MODE_PROVIDED_FILE " /usr/bin/devel-su"
57
58
#define DEVELOPER_MODE_PACKAGE " jolla-developer-mode"
59
+ #define DEVELOPER_MODE_PACKAGE_PRELOAD_DIR " /var/lib/jolla-developer-mode/preloaded/"
58
60
59
61
/* D-Bus service */
60
62
#define USB_MODED_SERVICE " com.meego.usb_moded"
@@ -84,6 +86,17 @@ static QMap<QString,QString> enumerate_network_interfaces()
84
86
return result;
85
87
}
86
88
89
+ static QString get_cached_package (const QString &version)
90
+ {
91
+ QDir dir (DEVELOPER_MODE_PACKAGE_PRELOAD_DIR);
92
+ QStringList filters;
93
+ filters << QStringLiteral (" %1-%2.*.rpm" ).arg (DEVELOPER_MODE_PACKAGE).arg (version);
94
+ auto preloaded = dir.entryList (filters, QDir::Files, QDir::Name);
95
+ if (preloaded.empty ())
96
+ return QString ();
97
+ return dir.absoluteFilePath (preloaded.last ());
98
+ }
99
+
87
100
DeveloperModeSettings::DeveloperModeSettings (QObject *parent)
88
101
: QObject(parent)
89
102
, m_usbModeDaemon(USB_MODED_SERVICE, USB_MODED_PATH, USB_MODED_INTERFACE, QDBusConnection::systemBus())
@@ -97,6 +110,8 @@ DeveloperModeSettings::DeveloperModeSettings(QObject *parent)
97
110
, m_transactionRole(PackageKit::Transaction::RoleUnknown)
98
111
, m_transactionStatus(PackageKit::Transaction::StatusUnknown)
99
112
, m_refreshedForInstall(false )
113
+ , m_localInstallFailed(false )
114
+ , m_localDeveloperModePackagePath(get_cached_package(QStringLiteral(" *" ))) // Initialized to possibly incompatible package
100
115
{
101
116
int uid = getdef_num (" UID_MIN" , -1 );
102
117
struct passwd *pwd;
@@ -106,6 +121,23 @@ DeveloperModeSettings::DeveloperModeSettings(QObject *parent)
106
121
qCWarning (lcDeveloperModeLog) << " Failed to return username using getpwuid()" ;
107
122
}
108
123
124
+ // Resolve and update local package path
125
+ if (!m_localDeveloperModePackagePath.isEmpty ()) {
126
+ PackageKit::Transaction *resolvePackage = PackageKit::Daemon::resolve (DEVELOPER_MODE_PACKAGE" -preload" , PackageKit::Transaction::FilterInstalled);
127
+ connect (resolvePackage, &PackageKit::Transaction::errorCode, this , &DeveloperModeSettings::reportTransactionErrorCode);
128
+ connect (resolvePackage, &PackageKit::Transaction::package,
129
+ this , [this ](PackageKit::Transaction::Info info, const QString &packageID, const QString &summary) {
130
+ Q_UNUSED (summary)
131
+ Q_ASSERT (info == PackageKit::Transaction::InfoInstalled);
132
+ const QString version = PackageKit::Transaction::packageVersion (packageID);
133
+ m_localDeveloperModePackagePath = get_cached_package (version);
134
+ if (m_localDeveloperModePackagePath.isEmpty ()) {
135
+ emit repositoryAccessRequiredChanged ();
136
+ }
137
+ qCDebug (lcDeveloperModeLog) << " Preload package version: " << version << " , local package path: " << m_localDeveloperModePackagePath;
138
+ });
139
+ }
140
+
109
141
refresh ();
110
142
111
143
// TODO: Watch WLAN / USB IP addresses for changes
@@ -146,6 +178,12 @@ int DeveloperModeSettings::workProgress() const
146
178
return m_workProgress;
147
179
}
148
180
181
+ bool DeveloperModeSettings::repositoryAccessRequired () const
182
+ {
183
+ // Aka local-install-of-developer-mode-package-is-not-possible
184
+ return m_localInstallFailed || m_localDeveloperModePackagePath.isEmpty ();
185
+ }
186
+
149
187
void DeveloperModeSettings::setDeveloperMode (bool enabled)
150
188
{
151
189
if (m_developerModeEnabled != enabled) {
@@ -233,72 +271,114 @@ void DeveloperModeSettings::refreshPackageCacheAndInstall()
233
271
void DeveloperModeSettings::resolveAndExecute (Command command)
234
272
{
235
273
setWorkStatus (Preparing);
274
+ m_workProgress = 0 ;
236
275
m_developerModePackageId.clear (); // might differ between installed/available
237
276
238
- PackageKit::Transaction::Filters filters;
239
- if (command == RemoveCommand) {
240
- filters = PackageKit::Transaction::FilterInstalled;
241
- } else {
242
- filters = PackageKit::Transaction::FilterNewest;
243
- }
244
- PackageKit::Transaction *resolvePackage = PackageKit::Daemon::resolve (DEVELOPER_MODE_PACKAGE, filters);
277
+ if (command == InstallCommand && !m_localInstallFailed && !m_localDeveloperModePackagePath.isEmpty ()) {
278
+ // Resolve which version of developer mode package is expected
279
+ PackageKit::Transaction *resolvePackage = PackageKit::Daemon::resolve (DEVELOPER_MODE_PACKAGE" -preload" , PackageKit::Transaction::FilterInstalled);
280
+ connect (resolvePackage, &PackageKit::Transaction::errorCode, this , &DeveloperModeSettings::reportTransactionErrorCode);
281
+ connect (resolvePackage, &PackageKit::Transaction::package,
282
+ this , [this ](PackageKit::Transaction::Info info, const QString &packageID, const QString &summary) {
283
+ Q_UNUSED (summary)
284
+ Q_ASSERT (info == PackageKit::Transaction::InfoInstalled);
285
+ const QString version = PackageKit::Transaction::packageVersion (packageID);
286
+ m_localDeveloperModePackagePath = get_cached_package (version);
287
+ emit repositoryAccessRequiredChanged ();
288
+ qCDebug (lcDeveloperModeLog) << " Preload package version: " << version << " , local package path: " << m_localDeveloperModePackagePath;
289
+ });
290
+
291
+ connect (resolvePackage, &PackageKit::Transaction::finished,
292
+ this , [this ](PackageKit::Transaction::Exit status, uint runtime) {
293
+ Q_UNUSED (runtime)
294
+ if (status != PackageKit::Transaction::ExitSuccess || m_localDeveloperModePackagePath.isEmpty ()) {
295
+ qCDebug (lcDeveloperModeLog) << " Preloaded package not found, must use remote package" ;
296
+ // No cached package => install from repos
297
+ resolveAndExecute (InstallCommand);
298
+ } else {
299
+ PackageKit::Transaction *tx = PackageKit::Daemon::installFiles (QStringList () << m_localDeveloperModePackagePath);
300
+ connectCommandSignals (tx);
301
+ connect (tx, &PackageKit::Transaction::finished,
302
+ this , [this ](PackageKit::Transaction::Exit status, uint runtime) {
303
+ if (status == PackageKit::Transaction::ExitSuccess) {
304
+ qCDebug (lcDeveloperModeLog) << " Developer mode installation from local package transaction done:" << status << runtime;
305
+ resetState ();
306
+ } else if (status == PackageKit::Transaction::ExitFailed) {
307
+ qCWarning (lcDeveloperModeLog) << " Developer mode installation from local package failed, trying from repos" ;
308
+ m_localInstallFailed = true ;
309
+ emit repositoryAccessRequiredChanged ();
310
+ resolveAndExecute (InstallCommand); // TODO: If repo access is not available this can not bail out
311
+ } // else ExitUnknown (ignored)
312
+ });
313
+ }
314
+ });
245
315
246
- connect (resolvePackage, &PackageKit::Transaction::errorCode, this , &DeveloperModeSettings::reportTransactionErrorCode);
247
- connect (resolvePackage, &PackageKit::Transaction::package,
248
- this , [this ](PackageKit::Transaction::Info info, const QString &packageId, const QString &summary) {
249
- qCDebug (lcDeveloperModeLog) << " Package transaction:" << info << packageId << " summary:" << summary;
250
- m_developerModePackageId = packageId;
251
- });
316
+ } else {
317
+ PackageKit::Transaction::Filters filters;
318
+ if (command == RemoveCommand) {
319
+ filters = PackageKit::Transaction::FilterInstalled;
320
+ } else {
321
+ filters = PackageKit::Transaction::FilterNewest;
322
+ }
323
+ PackageKit::Transaction *resolvePackage = PackageKit::Daemon::resolve (DEVELOPER_MODE_PACKAGE, filters);
324
+
325
+ connect (resolvePackage, &PackageKit::Transaction::errorCode, this , &DeveloperModeSettings::reportTransactionErrorCode);
326
+ connect (resolvePackage, &PackageKit::Transaction::package,
327
+ this , [this ](PackageKit::Transaction::Info info, const QString &packageId, const QString &summary) {
328
+ qCDebug (lcDeveloperModeLog) << " Package transaction:" << info << packageId << " summary:" << summary;
329
+ m_developerModePackageId = packageId;
330
+ });
331
+
332
+ connect (resolvePackage, &PackageKit::Transaction::finished,
333
+ this , [this , command](PackageKit::Transaction::Exit status, uint runtime) {
334
+ Q_UNUSED (runtime)
335
+
336
+ if (status != PackageKit::Transaction::ExitSuccess || m_developerModePackageId.isEmpty ()) {
337
+ if (command == InstallCommand) {
338
+ if (m_refreshedForInstall) {
339
+ qCWarning (lcDeveloperModeLog) << " Failed to install developer mode, package didn't resolve." ;
340
+ resetState ();
341
+ } else {
342
+ refreshPackageCacheAndInstall (); // try once if it helps
343
+ }
344
+ } else if (command == RemoveCommand) {
345
+ qCWarning (lcDeveloperModeLog) << " Removing developer mode but package didn't resolve into anything. Shouldn't happen." ;
346
+ resetState ();
347
+ }
252
348
253
- connect (resolvePackage, &PackageKit::Transaction::finished,
254
- this , [ this , command]( PackageKit::Transaction::Exit status, uint runtime) {
255
- Q_UNUSED (runtime)
349
+ } else if (command == InstallCommand) {
350
+ PackageKit::Transaction *tx = PackageKit::Daemon::installPackage (m_developerModePackageId);
351
+ connectCommandSignals (tx);
256
352
257
- if (status != PackageKit::Transaction::ExitSuccess || m_developerModePackageId.isEmpty ()) {
258
- if (command == InstallCommand) {
259
353
if (m_refreshedForInstall) {
260
- qCWarning (lcDeveloperModeLog) << " Failed to install developer mode, package didn't resolve." ;
261
- resetState ();
354
+ connect (tx, &PackageKit::Transaction::finished,
355
+ this , [this ](PackageKit::Transaction::Exit status, uint runtime) {
356
+ qCDebug (lcDeveloperModeLog) << " Developer mode installation transaction done (with refresh):" << status << runtime;
357
+ resetState ();
358
+ });
262
359
} else {
263
- refreshPackageCacheAndInstall (); // try once if it helps
360
+ connect (tx, &PackageKit::Transaction::finished,
361
+ this , [this ](PackageKit::Transaction::Exit status, uint runtime) {
362
+ if (status == PackageKit::Transaction::ExitSuccess) {
363
+ qCDebug (lcDeveloperModeLog) << " Developer mode installation transaction done:" << status << runtime;
364
+ resetState ();
365
+ } else {
366
+ qCDebug (lcDeveloperModeLog) << " Developer mode installation failed, trying again after refresh" ;
367
+ refreshPackageCacheAndInstall ();
368
+ }
369
+ });
264
370
}
265
- } else if (command == RemoveCommand) {
266
- qCWarning (lcDeveloperModeLog) << " Removing developer mode but package didn't resolve into anything. Shouldn't happen." ;
267
- resetState ();
268
- }
269
-
270
- } else if (command == InstallCommand) {
271
- PackageKit::Transaction *tx = PackageKit::Daemon::installPackage (m_developerModePackageId);
272
- connectCommandSignals (tx);
273
-
274
- if (m_refreshedForInstall) {
275
- connect (tx, &PackageKit::Transaction::finished,
276
- this , [this ](PackageKit::Transaction::Exit status, uint runtime) {
277
- qCDebug (lcDeveloperModeLog) << " Developer mode installation transaction done (with refresh):" << status << runtime;
278
- resetState ();
279
- });
280
371
} else {
372
+ PackageKit::Transaction *tx = PackageKit::Daemon::removePackage (m_developerModePackageId, true , true );
373
+ connectCommandSignals (tx);
281
374
connect (tx, &PackageKit::Transaction::finished,
282
375
this , [this ](PackageKit::Transaction::Exit status, uint runtime) {
283
- if (status == PackageKit::Transaction::ExitSuccess) {
284
- qCDebug (lcDeveloperModeLog) << " Developer mode installation transaction done:" << status << runtime;
285
- resetState ();
286
- } else {
287
- qCDebug (lcDeveloperModeLog) << " Developer mode installation failed, trying again after refresh" ;
288
- refreshPackageCacheAndInstall ();
289
- }
376
+ qCDebug (lcDeveloperModeLog) << " Developer mode removal transaction done:" << status << runtime;
377
+ resetState ();
290
378
});
291
379
}
292
- } else {
293
- PackageKit::Transaction *tx = PackageKit::Daemon::removePackage (m_developerModePackageId, true , true );
294
- connectCommandSignals (tx);
295
- connect (tx, &PackageKit::Transaction::finished,
296
- this , [this ](PackageKit::Transaction::Exit status, uint runtime) {
297
- qCDebug (lcDeveloperModeLog) << " Developer mode removal transaction done:" << status << runtime;
298
- resetState ();
299
- });
300
- }
301
- });
380
+ });
381
+ }
302
382
}
303
383
304
384
void DeveloperModeSettings::connectCommandSignals (PackageKit::Transaction *transaction)
@@ -319,19 +399,16 @@ void DeveloperModeSettings::connectCommandSignals(PackageKit::Transaction *trans
319
399
320
400
void DeveloperModeSettings::updateState (int percentage, PackageKit::Transaction::Status status, PackageKit::Transaction::Role role)
321
401
{
322
- // Do not update progress when finished.
323
- if (status == PackageKit::Transaction::StatusFinished) {
324
- return ;
325
- }
326
-
327
402
// Expected changes from PackageKit when installing packages:
328
- // 1. Change to 'install packages' role
403
+ // 1. Change to 'install packages' role or 'install files' if installing from local package file
329
404
// 2. Status changes:
330
405
// setup -> refresh cache -> query -> resolve deps -> install (refer to as 'Preparing' status)
331
406
// -> download ('DownloadingPackages' status)
332
407
// -> install ('InstallingPackages' status)
333
408
// -> finished
334
409
//
410
+ // If installing from local package fails, it starts over!
411
+ //
335
412
// Expected changes from PackageKit when removing packages:
336
413
// 1. Change to 'remove packages' role
337
414
// 2. Status changes:
@@ -347,10 +424,17 @@ void DeveloperModeSettings::updateState(int percentage, PackageKit::Transaction:
347
424
m_transactionRole = role;
348
425
m_transactionStatus = status;
349
426
427
+ // Do not update progress when finished or role is unknown.
428
+ if (m_transactionStatus == PackageKit::Transaction::StatusFinished
429
+ || m_transactionRole == PackageKit::Transaction::RoleUnknown) {
430
+ return ;
431
+ }
432
+
350
433
if (percentage >= 0 && percentage <= 100 ) {
351
434
int rangeStart = 0 ;
352
435
int rangeEnd = 0 ;
353
- if (m_transactionRole == PackageKit::Transaction::RoleInstallPackages) {
436
+ if (m_transactionRole == PackageKit::Transaction::RoleInstallPackages
437
+ || m_transactionRole == PackageKit::Transaction::RoleInstallFiles) {
354
438
switch (m_transactionStatus) {
355
439
case PackageKit::Transaction::StatusRefreshCache: // 0-10 %
356
440
rangeStart = 0 ;
@@ -362,7 +446,10 @@ void DeveloperModeSettings::updateState(int percentage, PackageKit::Transaction:
362
446
rangeEnd = 20 ;
363
447
break ;
364
448
case PackageKit::Transaction::StatusDownload: // 20-60 %
365
- workStatus = DownloadingPackages;
449
+ // Skip downloading when installing from local file
450
+ if (m_transactionRole != PackageKit::Transaction::RoleInstallFiles) {
451
+ workStatus = DownloadingPackages;
452
+ }
366
453
rangeStart = 20 ;
367
454
rangeEnd = 60 ;
368
455
break ;
0 commit comments