File indexing completed on 2024-04-28 05:26:47
0001 /* 0002 * SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "UnattendedUpdates.h" 0008 #include "DiscoverNotifier.h" 0009 #include "updatessettings.h" 0010 #include <KIdleTime> 0011 #include <QDateTime> 0012 #include <QDebug> 0013 #include <QProcess> 0014 #include <chrono> 0015 0016 UnattendedUpdates::UnattendedUpdates(DiscoverNotifier *parent) 0017 : QObject(parent) 0018 { 0019 connect(parent, &DiscoverNotifier::stateChanged, this, &UnattendedUpdates::checkNewState); 0020 connect(KIdleTime::instance(), QOverload<int, int>::of(&KIdleTime::timeoutReached), this, &UnattendedUpdates::triggerUpdate); 0021 0022 checkNewState(); 0023 } 0024 0025 UnattendedUpdates::~UnattendedUpdates() noexcept 0026 { 0027 if (m_idleTimeoutId.has_value()) { 0028 KIdleTime::instance()->removeIdleTimeout(m_idleTimeoutId.value()); 0029 } 0030 } 0031 0032 void UnattendedUpdates::checkNewState() 0033 { 0034 using namespace std::chrono_literals; 0035 DiscoverNotifier *notifier = static_cast<DiscoverNotifier *>(parent()); 0036 0037 // Only allow offline updating every 3h. It should keep some peace to our users, especially on rolling distros 0038 const QDateTime updateableTime = notifier->settings()->lastUnattendedTrigger().addSecs(std::chrono::seconds(3h).count()); 0039 if (updateableTime > QDateTime::currentDateTimeUtc()) { 0040 qDebug() << "skipping update, already updated on" << notifier->settings()->lastUnattendedTrigger().toString(); 0041 return; 0042 } 0043 0044 const bool doTrigger = notifier->hasUpdates() && !notifier->isBusy(); 0045 if (doTrigger && !m_idleTimeoutId.has_value()) { 0046 qDebug() << "waiting for an idle moment"; 0047 // If the system is untouched for 15 minutes, trigger the unattened update 0048 m_idleTimeoutId = KIdleTime::instance()->addIdleTimeout(int(std::chrono::milliseconds(15min).count())); 0049 } else if (!doTrigger && m_idleTimeoutId.has_value()) { 0050 qDebug() << "nothing to do"; 0051 KIdleTime::instance()->removeIdleTimeout(m_idleTimeoutId.value()); 0052 m_idleTimeoutId.reset(); 0053 } 0054 } 0055 0056 void UnattendedUpdates::triggerUpdate(int timeoutId) 0057 { 0058 if (!m_idleTimeoutId.has_value() || timeoutId != m_idleTimeoutId.value()) { 0059 return; 0060 } 0061 0062 KIdleTime::instance()->removeIdleTimeout(m_idleTimeoutId.value()); 0063 m_idleTimeoutId.reset(); 0064 0065 DiscoverNotifier *notifier = static_cast<DiscoverNotifier *>(parent()); 0066 if (!notifier->hasUpdates() || notifier->isBusy()) { 0067 return; 0068 } 0069 0070 auto process = new QProcess(this); 0071 connect(process, &QProcess::errorOccurred, this, [](QProcess::ProcessError error) { 0072 qWarning() << "Error running plasma-discover-update" << error; 0073 }); 0074 connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this, process](int exitCode, QProcess::ExitStatus exitStatus) { 0075 qDebug() << "Finished running plasma-discover-update" << exitCode << exitStatus; 0076 DiscoverNotifier *notifier = static_cast<DiscoverNotifier *>(parent()); 0077 process->deleteLater(); 0078 notifier->settings()->setLastUnattendedTrigger(QDateTime::currentDateTimeUtc()); 0079 notifier->settings()->save(); 0080 notifier->setBusy(false); 0081 }); 0082 0083 notifier->setBusy(true); 0084 process->start(QStringLiteral("plasma-discover-update"), {QStringLiteral("--offline")}); 0085 qInfo() << "started unattended update" << QDateTime::currentDateTimeUtc(); 0086 }