Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Plasma
Discover
Commits
95afc5ed
Commit
95afc5ed
authored
Apr 15, 2021
by
Mariam Fahmy
Committed by
Aleix Pol Gonzalez
Apr 15, 2021
Browse files
Add support for rpm-ostree
This allows to upgrade systems based on rpm-ostree like Fedora Kinoite or Fedora Silverblue.
parent
ebd45f23
Changes
14
Expand all
Hide whitespace changes
Inline
Side-by-side
libdiscover/backends/CMakeLists.txt
View file @
95afc5ed
...
...
@@ -45,4 +45,9 @@ if(BUILD_FwupdBackend AND TARGET PkgConfig::Fwupd)
add_subdirectory
(
FwupdBackend
)
endif
()
option
(
BUILD_RpmOstreeBackend
"Build RpmOstree support."
"ON"
)
if
(
BUILD_RpmOstreeBackend
)
add_subdirectory
(
RpmOstreeBackend
)
endif
()
libdiscover/backends/RpmOstreeBackend/CMakeLists.txt
0 → 100644
View file @
95afc5ed
set
(
CMAKE_MODULE_PATH
${
ECM_MODULE_DIR
}
)
set_source_files_properties
(
org.projectatomic.rpmostree1.xml PROPERTIES
INCLUDE dbustypes.h
)
set
(
rpmostree1_xml
${
CMAKE_INSTALL_PREFIX
}
/
${
DBUS_INTERFACES_INSTALL_DIR
}
/org.projectatomic.rpmostree1.xml
)
qt5_add_dbus_interface
(
ostree1_SRCS org.projectatomic.rpmostree1.xml rpmostree1
)
add_library
(
rpmostree-backend MODULE RpmOstreeResource.cpp RpmOstreeBackend.cpp RpmOstreeTransaction.cpp RpmOstree.qrc
${
ostree1_SRCS
}
)
target_link_libraries
(
rpmostree-backend PRIVATE Discover::Common Qt5::DBus KF5::CoreAddons KF5::I18n
)
install
(
TARGETS rpmostree-backend DESTINATION
${
PLUGIN_INSTALL_DIR
}
/discover
)
add_library
(
RpmOstreeNotifier MODULE RpmOstreeNotifier.cpp
)
target_link_libraries
(
RpmOstreeNotifier Discover::Notifiers Qt5::Concurrent PkgConfig::Flatpak
)
set_target_properties
(
RpmOstreeNotifier PROPERTIES INSTALL_RPATH
${
CMAKE_INSTALL_FULL_LIBDIR
}
/plasma-discover
)
install
(
TARGETS RpmOstreeNotifier DESTINATION
${
PLUGIN_INSTALL_DIR
}
/discover-notifier
)
libdiscover/backends/RpmOstreeBackend/RpmOstree.qrc
0 → 100644
View file @
95afc5ed
<!DOCTYPE RCC>
<RCC
version=
"1.0"
>
<qresource>
<file>
qml/RemoteRefsButton.qml
</file>
</qresource>
</RCC>
libdiscover/backends/RpmOstreeBackend/RpmOstreeBackend.cpp
0 → 100644
View file @
95afc5ed
/*
* SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
* SPDX-FileCopyrightText: 2021 Mariam Fahmy Sobhy <mariamfahmy66@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include
"RpmOstreeBackend.h"
#include
"RpmOstreeResource.h"
#include
"RpmOstreeTransaction.h"
#include
<QDBusInterface>
#include
<QDBusMessage>
#include
<QDBusObjectPath>
#include
<QDBusPendingReply>
#include
<QDebug>
#include
<QList>
#include
<QMap>
#include
<QStringList>
#include
<QVariant>
#include
<QVariantList>
#include
<QFile>
#include
<Transaction/Transaction.h>
#include
<resources/SourcesModel.h>
#include
<resources/StandardBackendUpdater.h>
#include
<QStandardItemModel>
DISCOVER_BACKEND_PLUGIN
(
RpmOstreeBackend
)
class
RpmOstreeSourcesBackend
:
public
AbstractSourcesBackend
{
public:
explicit
RpmOstreeSourcesBackend
(
AbstractResourcesBackend
*
parent
)
:
AbstractSourcesBackend
(
parent
)
,
m_model
(
new
QStandardItemModel
(
this
))
{
auto
it
=
new
QStandardItem
(
QStringLiteral
(
"rpm-ostree"
));
it
->
setData
(
QStringLiteral
(
"rpm-ostree"
),
IdRole
);
m_model
->
appendRow
(
it
);
}
QAbstractItemModel
*
sources
()
override
{
return
m_model
;
}
bool
addSource
(
const
QString
&
)
override
{
return
false
;
}
bool
removeSource
(
const
QString
&
)
override
{
return
false
;
}
QString
idDescription
()
override
{
return
QStringLiteral
(
"rpm-ostree"
);
}
QVariantList
actions
()
const
override
{
return
{};
}
bool
supportsAdding
()
const
override
{
return
false
;
}
bool
canMoveSources
()
const
override
{
return
false
;
}
private:
QStandardItemModel
*
const
m_model
;
};
RpmOstreeBackend
::
RpmOstreeBackend
(
QObject
*
parent
)
:
AbstractResourcesBackend
(
parent
)
,
isDeploymentUpdate
(
true
)
,
m_fetching
(
true
)
,
m_reviews
(
AppStreamIntegration
::
global
()
->
reviews
())
,
m_updater
(
new
StandardBackendUpdater
(
this
))
{
connect
(
m_updater
,
&
StandardBackendUpdater
::
updatesCountChanged
,
this
,
&
RpmOstreeBackend
::
updatesCountChanged
);
getDeployments
();
SourcesModel
::
global
()
->
addSourcesBackend
(
new
RpmOstreeSourcesBackend
(
this
));
executeCheckUpdateProcess
();
executeRemoteRefsProcess
();
}
void
RpmOstreeBackend
::
getDeployments
()
{
// reading Deployments property from "org.projectatomic.rpmostree1.Sysroot" interface
QDBusInterface
interface
(
QStringLiteral
(
"org.projectatomic.rpmostree1"
),
QStringLiteral
(
"/org/projectatomic/rpmostree1/Sysroot"
),
QStringLiteral
(
"org.freedesktop.DBus.Properties"
),
QDBusConnection
::
systemBus
());
QDBusMessage
result
=
interface
.
call
(
QStringLiteral
(
"Get"
),
QStringLiteral
(
"org.projectatomic.rpmostree1.Sysroot"
),
QStringLiteral
(
"Deployments"
));
QList
<
QVariant
>
outArgs
=
result
.
arguments
();
QVariant
first
=
outArgs
.
at
(
0
);
QDBusVariant
dbvFirst
=
first
.
value
<
QDBusVariant
>
();
QVariant
vFirst
=
dbvFirst
.
variant
();
QDBusArgument
dbusArgs
=
vFirst
.
value
<
QDBusArgument
>
();
// storing the extracted deployments from DBus
dbusArgs
.
beginArray
();
while
(
!
dbusArgs
.
atEnd
())
{
QMap
<
QString
,
QVariant
>
map
;
dbusArgs
>>
map
;
QDBusArgument
dbusArgsSignature
=
map
[
QStringLiteral
(
"signatures"
)].
value
<
QDBusArgument
>
();
dbusArgsSignature
>>
map
[
QStringLiteral
(
"signatures"
)];
QDBusVariant
dbvFirst1
=
map
[
QStringLiteral
(
"signatures"
)].
value
<
QDBusVariant
>
();
QVariant
vFirst1
=
dbvFirst1
.
variant
();
QDBusArgument
dbusArgsSign
=
vFirst1
.
value
<
QDBusArgument
>
();
dbusArgsSign
>>
map
[
QStringLiteral
(
"signatures"
)];
QString
baseVersion
=
map
[
QStringLiteral
(
"version"
)].
toString
();
QString
deploymentName
=
baseVersion
;
deploymentName
.
remove
(
8
,
deploymentName
.
size
()
-
1
);
baseVersion
.
remove
(
0
,
7
);
// creating a deployment struct
DeploymentInformation
extractDeployment
;
extractDeployment
.
name
=
deploymentName
;
extractDeployment
.
baseVersion
=
baseVersion
;
extractDeployment
.
booted
=
map
[
QStringLiteral
(
"booted"
)].
toBool
();
extractDeployment
.
baseChecksum
=
map
[
QStringLiteral
(
"checksum"
)].
toString
();
extractDeployment
.
layeredPackages
=
map
[
QStringLiteral
(
"packages"
)].
toString
();
extractDeployment
.
localPackages
=
map
[
QStringLiteral
(
"requested-local-packages"
)].
toString
();
extractDeployment
.
signature
=
map
[
QStringLiteral
(
"signatures"
)].
toString
();
extractDeployment
.
origin
=
map
[
QStringLiteral
(
"origin"
)].
toString
();
extractDeployment
.
timestamp
=
map
[
QStringLiteral
(
"timestamp"
)].
toULongLong
();
deploymentsList
.
push_back
(
extractDeployment
);
}
dbusArgs
.
endArray
();
// create a resource for each deployment
for
(
const
DeploymentInformation
&
deployment
:
deploymentsList
)
{
QString
name
=
deployment
.
name
;
QString
baseVersion
=
deployment
.
baseVersion
;
QString
baseChecksum
=
deployment
.
baseChecksum
;
QString
signature
=
deployment
.
signature
;
QString
layeredPackages
=
deployment
.
layeredPackages
;
QString
localPackages
=
deployment
.
localPackages
;
QString
origin
=
deployment
.
origin
;
qulonglong
timestamp
=
deployment
.
timestamp
;
bool
booted
=
deployment
.
booted
;
RpmOstreeResource
*
deploymentResource
=
new
RpmOstreeResource
(
name
,
baseVersion
,
baseChecksum
,
signature
,
layeredPackages
,
localPackages
,
origin
,
timestamp
,
this
);
// changing the state of the booted deployment resource to Installed.
if
(
booted
)
{
deploymentResource
->
setState
(
AbstractResource
::
Installed
);
}
m_resources
.
push_back
(
deploymentResource
);
}
}
void
RpmOstreeBackend
::
toggleFetching
()
{
m_fetching
=
!
m_fetching
;
checkForUpdatesNeeded
();
emit
fetchingChanged
();
}
void
RpmOstreeBackend
::
checkForUpdatesNeeded
()
{
if
(
!
m_newVersion
.
isEmpty
())
{
m_newVersion
.
remove
(
0
,
25
);
m_newVersion
.
remove
(
13
,
m_newVersion
.
size
()
-
13
);
m_resources
[
0
]
->
setNewVersion
(
m_newVersion
);
m_resources
[
0
]
->
setState
(
AbstractResource
::
Upgradeable
);
connect
(
m_resources
[
0
],
&
RpmOstreeResource
::
stateChanged
,
this
,
&
RpmOstreeBackend
::
updatesCountChanged
);
}
}
void
RpmOstreeBackend
::
executeCheckUpdateProcess
()
{
QProcess
*
process
=
new
QProcess
();
connect
(
process
,
&
QProcess
::
readyReadStandardError
,
[
process
]()
{
QByteArray
readError
=
process
->
readAllStandardError
();
});
// catch data output
connect
(
process
,
&
QProcess
::
readyReadStandardOutput
,
this
,
[
process
,
this
]()
{
QByteArray
readOutput
=
process
->
readAllStandardOutput
();
this
->
getQProcessUpdateOutput
(
readOutput
);
});
// delete process instance when done, and get the exit status to handle errors.
connect
(
process
,
QOverload
<
int
,
QProcess
::
ExitStatus
>::
of
(
&
QProcess
::
finished
),
[
=
](
int
exitCode
,
QProcess
::
ExitStatus
exitStatus
)
{
qWarning
()
<<
"process exited with code "
<<
exitCode
;
toggleFetching
();
process
->
deleteLater
();
});
process
->
setProcessChannelMode
(
QProcess
::
MergedChannels
);
process
->
start
(
QStringLiteral
(
"rpm-ostree update --check"
));
}
void
RpmOstreeBackend
::
getQProcessUpdateOutput
(
QByteArray
readOutput
)
{
QList
<
QByteArray
>
checkUpdateOutput
=
readOutput
.
split
(
'\n'
);
for
(
const
QByteArray
&
output
:
checkUpdateOutput
)
{
if
(
output
.
contains
(
QByteArray
(
"Version"
)))
{
m_newVersion
=
QString
::
fromLocal8Bit
(
output
);
}
}
}
void
RpmOstreeBackend
::
executeRemoteRefsProcess
()
{
if
(
!
m_remoteRefsList
.
isEmpty
())
m_remoteRefsList
.
clear
();
QProcess
*
process
=
new
QProcess
(
this
);
connect
(
process
,
&
QProcess
::
readyReadStandardError
,
[
process
]()
{
QByteArray
readError
=
process
->
readAllStandardError
();
});
// catch data output
connect
(
process
,
&
QProcess
::
readyReadStandardOutput
,
this
,
[
process
,
this
]()
{
QByteArray
readOutput
=
process
->
readAllStandardOutput
();
this
->
getQProcessRefsOutput
(
readOutput
);
});
// delete process instance when done, and get the exit status to handle errors.
QObject
::
connect
(
process
,
QOverload
<
int
,
QProcess
::
ExitStatus
>::
of
(
&
QProcess
::
finished
),
[
=
](
int
exitCode
,
QProcess
::
ExitStatus
exitStatus
)
{
qWarning
()
<<
"process exited with code "
<<
exitCode
;
settingRemoteRefsDeploymentResource
();
process
->
deleteLater
();
});
process
->
setProcessChannelMode
(
QProcess
::
MergedChannels
);
process
->
start
(
QStringLiteral
(
"ostree --repo=/ostree/repo remote refs kinoite"
));
}
void
RpmOstreeBackend
::
getQProcessRefsOutput
(
QByteArray
readOutput
)
{
QList
<
QByteArray
>
remoteRefsList
;
remoteRefsList
=
readOutput
.
split
(
'\n'
);
QString
kinoite
=
QStringLiteral
(
"kinoite"
);
for
(
const
QByteArray
&
refs
:
remoteRefsList
)
{
QString
refsToString
=
QString
::
fromLocal8Bit
(
refs
);
if
(
refsToString
.
count
(
kinoite
)
<=
1
)
continue
;
m_remoteRefsList
.
push_back
(
refsToString
);
}
}
void
RpmOstreeBackend
::
settingRemoteRefsDeploymentResource
()
{
m_resources
[
0
]
->
setRemoteRefsList
(
m_remoteRefsList
);
}
int
RpmOstreeBackend
::
updatesCount
()
const
{
return
m_updater
->
updatesCount
();
}
bool
RpmOstreeBackend
::
isValid
()
const
{
return
QFile
::
exists
(
QStringLiteral
(
"/run/ostree-booted"
));
}
ResultsStream
*
RpmOstreeBackend
::
search
(
const
AbstractResourcesBackend
::
Filters
&
filter
)
{
QVector
<
AbstractResource
*>
res
;
for
(
AbstractResource
*
r
:
m_resources
)
{
if
(
r
->
state
()
>=
filter
.
state
)
res
.
push_back
(
r
);
}
return
new
ResultsStream
(
QStringLiteral
(
"rpm-ostree"
),
res
);
}
Transaction
*
RpmOstreeBackend
::
installApplication
(
AbstractResource
*
app
,
const
AddonList
&
addons
)
{
updateCurrentDeployment
();
return
new
RpmOstreeTransaction
(
qobject_cast
<
RpmOstreeResource
*>
(
app
),
addons
,
Transaction
::
InstallRole
,
transactionUpdatePath
,
true
);
}
Transaction
*
RpmOstreeBackend
::
installApplication
(
AbstractResource
*
app
)
{
bool
deploymentUpdate
=
isDeploymentUpdate
;
if
(
isDeploymentUpdate
)
{
updateCurrentDeployment
();
}
else
{
isDeploymentUpdate
=
true
;
}
return
new
RpmOstreeTransaction
(
qobject_cast
<
RpmOstreeResource
*>
(
app
),
Transaction
::
InstallRole
,
transactionUpdatePath
,
deploymentUpdate
);
}
Transaction
*
RpmOstreeBackend
::
removeApplication
(
AbstractResource
*
)
{
return
nullptr
;
}
void
RpmOstreeBackend
::
updateCurrentDeployment
()
{
OrgProjectatomicRpmostree1OSInterface
interface
(
QStringLiteral
(
"org.projectatomic.rpmostree1"
),
QStringLiteral
(
"/org/projectatomic/rpmostree1/fedora"
),
QDBusConnection
::
systemBus
(),
this
);
QVariantMap
options
;
QVariantMap
modifiers
;
QString
name
;
QDBusPendingReply
<
QString
>
reply
=
interface
.
UpdateDeployment
(
modifiers
,
options
);
reply
.
waitForFinished
();
if
(
!
reply
.
isError
())
{
transactionUpdatePath
=
reply
.
argumentAt
(
0
).
value
<
QString
>
();
}
else
{
qDebug
()
<<
"Error occurs when performing the UpdateDeployment: "
<<
reply
.
error
();
}
}
void
RpmOstreeBackend
::
checkForUpdates
()
{
if
(
m_fetching
)
return
;
executeCheckUpdateProcess
();
executeRemoteRefsProcess
();
QTimer
::
singleShot
(
500
,
this
,
&
RpmOstreeBackend
::
toggleFetching
);
}
void
RpmOstreeBackend
::
perfromSystemUpgrade
(
QString
selectedRefs
)
{
OrgProjectatomicRpmostree1OSInterface
interface
(
QStringLiteral
(
"org.projectatomic.rpmostree1"
),
QStringLiteral
(
"/org/projectatomic/rpmostree1/fedora"
),
QDBusConnection
::
systemBus
(),
this
);
isDeploymentUpdate
=
false
;
QVariantMap
options
;
QStringList
packages
;
QDBusPendingReply
<
QString
>
reply
=
interface
.
Rebase
(
options
,
selectedRefs
,
packages
);
reply
.
waitForFinished
();
if
(
!
reply
.
isError
())
{
transactionUpdatePath
=
reply
.
argumentAt
(
0
).
value
<
QString
>
();
installApplication
(
m_resources
[
0
]);
}
else
{
qDebug
()
<<
"Error occurs when performing the Rebase: "
<<
reply
.
error
();
}
}
AbstractBackendUpdater
*
RpmOstreeBackend
::
backendUpdater
()
const
{
return
m_updater
;
}
AbstractReviewsBackend
*
RpmOstreeBackend
::
reviewsBackend
()
const
{
return
m_reviews
.
data
();
}
QString
RpmOstreeBackend
::
displayName
()
const
{
return
QStringLiteral
(
"rpm-ostree"
);
}
bool
RpmOstreeBackend
::
hasApplications
()
const
{
return
true
;
}
#include
"RpmOstreeBackend.moc"
libdiscover/backends/RpmOstreeBackend/RpmOstreeBackend.h
0 → 100644
View file @
95afc5ed
/*
* SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
* SPDX-FileCopyrightText: 2021 Mariam Fahmy Sobhy <mariamfahmy66@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#ifndef RPMOSTREE1BACKEND_H
#define RPMOSTREE1BACKEND_H
#include
<resources/AbstractResourcesBackend.h>
#include
"rpmostree1.h"
#include
<QMetaType>
#include
<QProcess>
#include
<QSharedPointer>
#include
<QThreadPool>
#include
<QtDBus/QDBusPendingReply>
#include
<AppStreamQt/component.h>
#include
<appstream/AppStreamIntegration.h>
#include
<appstream/OdrsReviewsBackend.h>
class
RpmOstreeReviewsBackend
;
class
OdrsReviewsBackend
;
class
RpmOstreeResource
;
class
StandardBackendUpdater
;
class
RpmOstreeBackend
:
public
AbstractResourcesBackend
{
Q_OBJECT
public:
explicit
RpmOstreeBackend
(
QObject
*
parent
=
nullptr
);
/*
* Getting the list of deployments from the rpm-ostree DBus class and
* converting each deployment to resource and detecting the currently running deployment.
* It is corresponding to "rpm-ostree status".
*/
void
getDeployments
();
/*
* Executing "rpm-ostree update --check" using QProcess to check if
* there is a new deployment version avaliable.
*/
void
executeCheckUpdateProcess
();
/*
* Getting the output resulting from executing the QProcess update check.
*/
void
getQProcessUpdateOutput
(
QByteArray
readOutput
);
/*
* Calling UpdateDeployment method from the rpm-ostree DBus class when
* there is a new deployment version avaliable .
*/
void
updateCurrentDeployment
();
/*
* Executing "ostree remote refs kinoite" using QProcess to get
* a list of the avaliable remote refs list.
*/
void
executeRemoteRefsProcess
();
/*
* Getting the output resulting from executing the QProcess remote refs list.
*/
void
getQProcessRefsOutput
(
QByteArray
readOutput
);
/*
* Setting the current remote refs list to the current running deployment resource.
*/
void
settingRemoteRefsDeploymentResource
();
/*
* Calling Rebase method from the rpm-ostree DBus class when
* there is a new kinoite refs.
*/
void
perfromSystemUpgrade
(
QString
);
int
updatesCount
()
const
override
;
AbstractBackendUpdater
*
backendUpdater
()
const
override
;
AbstractReviewsBackend
*
reviewsBackend
()
const
override
;
ResultsStream
*
search
(
const
AbstractResourcesBackend
::
Filters
&
search
)
override
;
// return true when OSTreeRPMBackend is ready to be loaded
bool
isValid
()
const
override
;
Transaction
*
installApplication
(
AbstractResource
*
)
override
;
Transaction
*
installApplication
(
AbstractResource
*
,
const
AddonList
&
)
override
;
Transaction
*
removeApplication
(
AbstractResource
*
)
override
;
bool
isFetching
()
const
override
{
return
m_fetching
;
}
void
checkForUpdates
()
override
;
QString
displayName
()
const
override
;
bool
hasApplications
()
const
override
;
public
Q_SLOTS
:
void
toggleFetching
();
private:
struct
DeploymentInformation
{
QString
name
;
bool
booted
;
QString
baseVersion
;
QString
baseChecksum
;
QString
layeredPackages
;
QString
localPackages
;
QString
signature
;
QString
origin
;
qulonglong
timestamp
;
};
QSharedPointer
<
OdrsReviewsBackend
>
m_reviews
;
StandardBackendUpdater
*
m_updater
;
QVector
<
RpmOstreeResource
*>
m_resources
;
QVector
<
DeploymentInformation
>
deploymentsList
;
QString
transactionUpdatePath
;
QStringList
m_remoteRefsList
;
bool
m_fetching
;
QString
m_newVersion
;
/*
* Checking if the required update is deployment update or system upgrade
* by default isDeploymentUpdate is true
*/
bool
isDeploymentUpdate
;
/*
* Extracting the new avaliable version of the deployment from the output
* resulting from QProcess update deployment and setting the current running
* deployment resource to AbstractResource::Upgradeable
*/
void
checkForUpdatesNeeded
();
};
#endif
\ No newline at end of file
libdiscover/backends/RpmOstreeBackend/RpmOstreeNotifier.cpp
0 → 100644
View file @
95afc5ed
/*
* SPDX-FileCopyrightText: 2021 Mariam Fahmy Sobhy <mariamfahmy66@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include
"RpmOstreeNotifier.h"
#include
<QDebug>
#include
<QFileSystemWatcher>
#include
<QProcess>
#include
<QTimer>
RpmOstreeNotifier
::
RpmOstreeNotifier
(
QObject
*
parent
)
:
BackendNotifierModule
(
parent
)
,
m_newUpdate
(
false
)
,
m_needsReboot
(
false
)
{
QFileSystemWatcher
*
watcher
=
new
QFileSystemWatcher
(
this
);
watcher
->
addPath
(
QStringLiteral
(
"/ostree/deploy/fedora/deploy/"
));
connect
(
watcher
,
&
QFileSystemWatcher
::
fileChanged
,
this
,
&
RpmOstreeNotifier
::
recheckSystemUpdateNeeded
);
QFileSystemWatcher
*
fileWatcher
=
new
QFileSystemWatcher
(
this
);
fileWatcher
->
addPath
(
QStringLiteral
(
"/tmp/discover-ostree-changed"
));
connect
(
fileWatcher
,
&
QFileSystemWatcher
::
fileChanged
,
this
,
&
RpmOstreeNotifier
::
nowNeedsReboot
);
}
RpmOstreeNotifier
::~
RpmOstreeNotifier
()
{
}
void
RpmOstreeNotifier
::
recheckSystemUpdateNeeded
()
{
QProcess
*
process
=
new
QProcess
();
connect
(
process
,
&
QProcess
::
readyReadStandardError
,
[
process
]()
{
QByteArray
readError
=
process
->