Skip to content
This repository was archived by the owner on Apr 28, 2022. It is now read-only.

Commit 2b7582e

Browse files
committed
Merge branch 'jb47559' into 'master'
Allow enabling developer mode from local package. See merge request mer-core/nemo-qml-plugin-systemsettings!126
2 parents ceaca90 + 72708b9 commit 2b7582e

File tree

3 files changed

+157
-64
lines changed

3 files changed

+157
-64
lines changed

rpm/nemo-qml-plugin-systemsettings.spec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Version: 0.5.27
44
Release: 1
55
Group: System/Libraries
66
License: BSD
7-
URL: https://git.merproject.org/mer-core/nemo-qml-plugin-systemsettings
7+
URL: https://git.sailfishos.org/mer-core/nemo-qml-plugin-systemsettings
88
Source0: %{name}-%{version}.tar.bz2
99
Requires(post): /sbin/ldconfig
1010
Requires(postun): /sbin/ldconfig

src/developermodesettings.cpp

Lines changed: 149 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
2-
* Copyright (C) 2013-2018 Jolla Ltd.
2+
* Copyright (c) 2013 – 2019 Jolla Ltd.
3+
* Copyright (c) 2019 Open Mobile Platform LLC.
34
* Contact: Thomas Perl <[email protected]>
45
* Contact: Raine Makelainen <[email protected]>
56
*
@@ -55,6 +56,7 @@
5556
/* A file that is provided by the developer mode package */
5657
#define DEVELOPER_MODE_PROVIDED_FILE "/usr/bin/devel-su"
5758
#define DEVELOPER_MODE_PACKAGE "jolla-developer-mode"
59+
#define DEVELOPER_MODE_PACKAGE_PRELOAD_DIR "/var/lib/jolla-developer-mode/preloaded/"
5860

5961
/* D-Bus service */
6062
#define USB_MODED_SERVICE "com.meego.usb_moded"
@@ -84,6 +86,17 @@ static QMap<QString,QString> enumerate_network_interfaces()
8486
return result;
8587
}
8688

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+
87100
DeveloperModeSettings::DeveloperModeSettings(QObject *parent)
88101
: QObject(parent)
89102
, m_usbModeDaemon(USB_MODED_SERVICE, USB_MODED_PATH, USB_MODED_INTERFACE, QDBusConnection::systemBus())
@@ -97,6 +110,8 @@ DeveloperModeSettings::DeveloperModeSettings(QObject *parent)
97110
, m_transactionRole(PackageKit::Transaction::RoleUnknown)
98111
, m_transactionStatus(PackageKit::Transaction::StatusUnknown)
99112
, m_refreshedForInstall(false)
113+
, m_localInstallFailed(false)
114+
, m_localDeveloperModePackagePath(get_cached_package(QStringLiteral("*"))) // Initialized to possibly incompatible package
100115
{
101116
int uid = getdef_num("UID_MIN", -1);
102117
struct passwd *pwd;
@@ -106,6 +121,23 @@ DeveloperModeSettings::DeveloperModeSettings(QObject *parent)
106121
qCWarning(lcDeveloperModeLog) << "Failed to return username using getpwuid()";
107122
}
108123

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+
109141
refresh();
110142

111143
// TODO: Watch WLAN / USB IP addresses for changes
@@ -146,6 +178,12 @@ int DeveloperModeSettings::workProgress() const
146178
return m_workProgress;
147179
}
148180

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+
149187
void DeveloperModeSettings::setDeveloperMode(bool enabled)
150188
{
151189
if (m_developerModeEnabled != enabled) {
@@ -233,72 +271,114 @@ void DeveloperModeSettings::refreshPackageCacheAndInstall()
233271
void DeveloperModeSettings::resolveAndExecute(Command command)
234272
{
235273
setWorkStatus(Preparing);
274+
m_workProgress = 0;
236275
m_developerModePackageId.clear(); // might differ between installed/available
237276

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+
});
245315

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+
}
252348

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);
256352

257-
if (status != PackageKit::Transaction::ExitSuccess || m_developerModePackageId.isEmpty()) {
258-
if (command == InstallCommand) {
259353
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+
});
262359
} 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+
});
264370
}
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-
});
280371
} else {
372+
PackageKit::Transaction *tx = PackageKit::Daemon::removePackage(m_developerModePackageId, true, true);
373+
connectCommandSignals(tx);
281374
connect(tx, &PackageKit::Transaction::finished,
282375
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();
290378
});
291379
}
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+
}
302382
}
303383

304384
void DeveloperModeSettings::connectCommandSignals(PackageKit::Transaction *transaction)
@@ -319,19 +399,16 @@ void DeveloperModeSettings::connectCommandSignals(PackageKit::Transaction *trans
319399

320400
void DeveloperModeSettings::updateState(int percentage, PackageKit::Transaction::Status status, PackageKit::Transaction::Role role)
321401
{
322-
// Do not update progress when finished.
323-
if (status == PackageKit::Transaction::StatusFinished) {
324-
return;
325-
}
326-
327402
// 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
329404
// 2. Status changes:
330405
// setup -> refresh cache -> query -> resolve deps -> install (refer to as 'Preparing' status)
331406
// -> download ('DownloadingPackages' status)
332407
// -> install ('InstallingPackages' status)
333408
// -> finished
334409
//
410+
// If installing from local package fails, it starts over!
411+
//
335412
// Expected changes from PackageKit when removing packages:
336413
// 1. Change to 'remove packages' role
337414
// 2. Status changes:
@@ -347,10 +424,17 @@ void DeveloperModeSettings::updateState(int percentage, PackageKit::Transaction:
347424
m_transactionRole = role;
348425
m_transactionStatus = status;
349426

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+
350433
if (percentage >= 0 && percentage <= 100) {
351434
int rangeStart = 0;
352435
int rangeEnd = 0;
353-
if (m_transactionRole == PackageKit::Transaction::RoleInstallPackages) {
436+
if (m_transactionRole == PackageKit::Transaction::RoleInstallPackages
437+
|| m_transactionRole == PackageKit::Transaction::RoleInstallFiles) {
354438
switch (m_transactionStatus) {
355439
case PackageKit::Transaction::StatusRefreshCache: // 0-10 %
356440
rangeStart = 0;
@@ -362,7 +446,10 @@ void DeveloperModeSettings::updateState(int percentage, PackageKit::Transaction:
362446
rangeEnd = 20;
363447
break;
364448
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+
}
366453
rangeStart = 20;
367454
rangeEnd = 60;
368455
break;

src/developermodesettings.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
2-
* Copyright (C) 2013 Jolla Ltd.
2+
* Copyright (c) 2013 – 2019 Jolla Ltd.
3+
* Copyright (c) 2019 Open Mobile Platform LLC.
34
* Contact: Thomas Perl <[email protected]>
45
*
56
* You may use this file under the terms of the BSD license as follows:
@@ -55,6 +56,7 @@ class SYSTEMSETTINGS_EXPORT DeveloperModeSettings : public QObject
5556
Q_PROPERTY(bool developerModeEnabled READ developerModeEnabled NOTIFY developerModeEnabledChanged)
5657
Q_PROPERTY(enum DeveloperModeSettings::Status workStatus READ workStatus NOTIFY workStatusChanged)
5758
Q_PROPERTY(int workProgress READ workProgress NOTIFY workProgressChanged)
59+
Q_PROPERTY(bool repositoryAccessRequired READ repositoryAccessRequired NOTIFY repositoryAccessRequiredChanged)
5860

5961
public:
6062
explicit DeveloperModeSettings(QObject *parent = NULL);
@@ -74,6 +76,7 @@ class SYSTEMSETTINGS_EXPORT DeveloperModeSettings : public QObject
7476
bool developerModeEnabled() const;
7577
enum DeveloperModeSettings::Status workStatus() const;
7678
int workProgress() const;
79+
bool repositoryAccessRequired() const;
7780

7881
Q_INVOKABLE void setDeveloperMode(bool enabled);
7982
Q_INVOKABLE void setUsbIpAddress(const QString &usbIpAddress);
@@ -85,6 +88,7 @@ class SYSTEMSETTINGS_EXPORT DeveloperModeSettings : public QObject
8588
void developerModeEnabledChanged();
8689
void workStatusChanged();
8790
void workProgressChanged();
91+
void repositoryAccessRequiredChanged();
8892

8993
private slots:
9094
void reportTransactionErrorCode(PackageKit::Transaction::Error code, const QString &details);
@@ -117,6 +121,8 @@ private slots:
117121
PackageKit::Transaction::Role m_transactionRole;
118122
PackageKit::Transaction::Status m_transactionStatus;
119123
bool m_refreshedForInstall;
124+
bool m_localInstallFailed;
125+
QString m_localDeveloperModePackagePath;
120126
};
121127

122128
Q_DECLARE_METATYPE(DeveloperModeSettings::Status)

0 commit comments

Comments
 (0)