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