Changeset View
Changeset View
Standalone View
Standalone View
libdiscover/backends/FlatpakBackend/FlatpakTransaction.cpp
Show All 21 Lines | |||||
22 | #include "FlatpakTransaction.h" | 22 | #include "FlatpakTransaction.h" | ||
23 | #include "FlatpakBackend.h" | 23 | #include "FlatpakBackend.h" | ||
24 | #include "FlatpakResource.h" | 24 | #include "FlatpakResource.h" | ||
25 | #include "FlatpakTransactionJob.h" | 25 | #include "FlatpakTransactionJob.h" | ||
26 | 26 | | |||
27 | #include <QDebug> | 27 | #include <QDebug> | ||
28 | #include <QTimer> | 28 | #include <QTimer> | ||
29 | 29 | | |||
30 | FlatpakTransaction::FlatpakTransaction(FlatpakInstallation *installation, FlatpakResource *app, Role role, bool delayStart) | 30 | extern "C" { | ||
31 | : FlatpakTransaction(installation, app, nullptr, role, delayStart) | 31 | #include <flatpak.h> | ||
32 | #include <gio/gio.h> | ||||
33 | #include <glib.h> | ||||
34 | } | ||||
35 | | ||||
36 | FlatpakTransaction::FlatpakTransaction(FlatpakResource *app, Role role, bool delayStart) | ||||
37 | : FlatpakTransaction(app, nullptr, role, delayStart) | ||||
32 | { | 38 | { | ||
33 | } | 39 | } | ||
34 | 40 | | |||
35 | FlatpakTransaction::FlatpakTransaction(FlatpakInstallation* installation, FlatpakResource *app, FlatpakResource *runtime, Transaction::Role role, bool delayStart) | 41 | FlatpakTransaction::FlatpakTransaction(FlatpakResource *app, FlatpakResource *runtime, Transaction::Role role, bool delayStart) | ||
36 | : Transaction(app->backend(), app, role, {}) | 42 | : Transaction(app->backend(), app, role, {}) | ||
37 | , m_appJobProgress(0) | | |||
38 | , m_runtimeJobProgress(0) | | |||
39 | , m_app(app) | 43 | , m_app(app) | ||
40 | , m_runtime(runtime) | 44 | , m_runtime(runtime) | ||
41 | , m_installation(installation) | | |||
42 | { | 45 | { | ||
43 | setCancellable(true); | 46 | setCancellable(true); | ||
44 | 47 | | |||
45 | if (!delayStart) { | 48 | if (!delayStart) { | ||
46 | QTimer::singleShot(0, this, &FlatpakTransaction::start); | 49 | QTimer::singleShot(0, this, &FlatpakTransaction::start); | ||
47 | } | 50 | } | ||
48 | } | 51 | } | ||
49 | 52 | | |||
50 | FlatpakTransaction::~FlatpakTransaction() | 53 | FlatpakTransaction::~FlatpakTransaction() | ||
51 | { | 54 | { | ||
52 | } | 55 | } | ||
53 | 56 | | |||
54 | void FlatpakTransaction::cancel() | 57 | void FlatpakTransaction::cancel() | ||
55 | { | 58 | { | ||
56 | Q_ASSERT(m_appJob); | 59 | Q_ASSERT(m_appJob); | ||
57 | m_appJob->cancel(); | 60 | foreach (const QPointer<FlatpakTransactionJob> &job, m_jobs) { | ||
58 | if (m_runtime) { | 61 | job->cancel(); | ||
59 | m_runtimeJob->cancel(); | | |||
60 | } | 62 | } | ||
61 | setStatus(CancelledStatus); | 63 | setStatus(CancelledStatus); | ||
62 | } | 64 | } | ||
63 | 65 | | |||
64 | void FlatpakTransaction::setRuntime(FlatpakResource *runtime) | 66 | void FlatpakTransaction::setRuntime(FlatpakResource *runtime) | ||
65 | { | 67 | { | ||
66 | m_runtime = runtime; | 68 | m_runtime = runtime; | ||
67 | } | 69 | } | ||
68 | 70 | | |||
69 | void FlatpakTransaction::start() | 71 | void FlatpakTransaction::start() | ||
70 | { | 72 | { | ||
71 | if (m_runtime) { | 73 | if (m_runtime) { | ||
72 | m_runtimeJob = new FlatpakTransactionJob(m_installation, m_runtime, role(), this); | 74 | // TODO related refs for runtime as well | ||
73 | connect(m_runtimeJob, &FlatpakTransactionJob::finished, this, &FlatpakTransaction::onRuntimeJobFinished); | 75 | QPointer<FlatpakTransactionJob> job = new FlatpakTransactionJob(m_runtime, QPair<QString, uint>(), role(), this); | ||
74 | connect(m_runtimeJob, &FlatpakTransactionJob::progressChanged, this, &FlatpakTransaction::onRuntimeJobProgressChanged); | 76 | connect(job, &FlatpakTransactionJob::finished, this, &FlatpakTransaction::onJobFinished); | ||
75 | m_runtimeJob->start(); | 77 | connect(job, &FlatpakTransactionJob::progressChanged, this, &FlatpakTransaction::onJobProgressChanged); | ||
76 | } | 78 | m_jobs << job; | ||
77 | 79 | | |||
78 | // App job will be started everytime | 80 | processRelatedRefs(m_runtime); | ||
79 | m_appJob = new FlatpakTransactionJob(m_installation, m_app, role(), this); | | |||
80 | connect(m_appJob, &FlatpakTransactionJob::finished, this, &FlatpakTransaction::onAppJobFinished); | | |||
81 | connect(m_appJob, &FlatpakTransactionJob::progressChanged, this, &FlatpakTransaction::onAppJobProgressChanged); | | |||
82 | m_appJob->start(); | | |||
83 | } | 81 | } | ||
84 | 82 | | |||
85 | void FlatpakTransaction::onAppJobFinished() | 83 | // App job will be added everytime | ||
86 | { | 84 | m_appJob = new FlatpakTransactionJob(m_app, QPair<QString, uint>(), role(), this); | ||
87 | m_appJobProgress = 100; | 85 | connect(m_appJob, &FlatpakTransactionJob::finished, this, &FlatpakTransaction::onJobFinished); | ||
86 | connect(m_appJob, &FlatpakTransactionJob::progressChanged, this, &FlatpakTransaction::onJobProgressChanged); | ||||
87 | m_jobs << m_appJob; | ||||
88 | 88 | | |||
89 | updateProgress(); | 89 | processRelatedRefs(m_app); | ||
90 | 90 | | |||
91 | if (!m_appJob->result()) { | | |||
92 | Q_EMIT passiveMessage(m_appJob->errorMessage()); | | |||
93 | } | | |||
94 | 91 | | |||
95 | if ((m_runtimeJob && m_runtimeJob->isFinished()) || !m_runtimeJob) { | 92 | // Now start all the jobs together | ||
96 | finishTransaction(); | 93 | foreach (const QPointer<FlatpakTransactionJob> &job, m_jobs) { | ||
94 | job->start(); | ||||
97 | } | 95 | } | ||
98 | } | 96 | } | ||
99 | 97 | | |||
100 | void FlatpakTransaction::onAppJobProgressChanged(int progress) | 98 | void FlatpakTransaction::processRelatedRefs(FlatpakResource* resource) | ||
101 | { | 99 | { | ||
102 | m_appJobProgress = progress; | 100 | g_autoptr(GPtrArray) refs = nullptr; | ||
101 | g_autoptr(GError) error = nullptr; | ||||
102 | g_autoptr(GCancellable) cancellable = g_cancellable_new();; | ||||
103 | QList<FlatpakResource> additionalResources; | ||||
104 | | ||||
105 | g_autofree gchar *ref = nullptr; | ||||
106 | ref = g_strdup_printf ("%s/%s/%s/%s", | ||||
107 | resource->typeAsString().toUtf8().constData(), | ||||
108 | resource->flatpakName().toUtf8().constData(), | ||||
109 | resource->arch().toUtf8().constData(), | ||||
110 | resource->branch().toUtf8().constData()); | ||||
111 | | ||||
112 | if (role() == Transaction::Role::InstallRole) { | ||||
113 | if (resource->state() == AbstractResource::Upgradeable) { | ||||
114 | refs = flatpak_installation_list_installed_related_refs_sync(resource->installation(), resource->origin().toUtf8().constData(), ref, cancellable, &error); | ||||
115 | if (error) { | ||||
116 | qWarning() << "Failed to list installed related refs for update: " << error->message; | ||||
117 | } | ||||
118 | } else { | ||||
119 | refs = flatpak_installation_list_remote_related_refs_sync(resource->installation(), resource->origin().toUtf8().constData(), ref, cancellable, &error); | ||||
120 | if (error) { | ||||
121 | qWarning() << "Failed to list related refs for installation: " << error->message; | ||||
122 | } | ||||
123 | } | ||||
124 | } else if (role() == Transaction::Role::RemoveRole) { | ||||
125 | refs = flatpak_installation_list_installed_related_refs_sync(resource->installation(), resource->origin().toUtf8().constData(), ref, cancellable, &error); | ||||
126 | if (error) { | ||||
127 | qWarning() << "Failed to list installed related refs for removal: " << error->message; | ||||
128 | } | ||||
129 | } | ||||
103 | 130 | | |||
104 | updateProgress(); | 131 | if (refs) { | ||
132 | for (uint i = 0; i < refs->len; i++) { | ||||
133 | FlatpakRef *flatpakRef = FLATPAK_REF(g_ptr_array_index(refs, i)); | ||||
134 | if (flatpak_related_ref_should_download(FLATPAK_RELATED_REF(flatpakRef))) { | ||||
135 | QPointer<FlatpakTransactionJob> job = new FlatpakTransactionJob(resource, QPair<QString, uint>(QString::fromUtf8(flatpak_ref_get_name(flatpakRef)), flatpak_ref_get_kind(flatpakRef)), role(), this); | ||||
136 | connect(job, &FlatpakTransactionJob::finished, this, &FlatpakTransaction::onJobFinished); | ||||
137 | connect(job, &FlatpakTransactionJob::progressChanged, this, &FlatpakTransaction::onJobProgressChanged); | ||||
138 | // Add to the list of all jobs | ||||
139 | m_jobs << job; | ||||
140 | } | ||||
141 | } | ||||
142 | } | ||||
105 | } | 143 | } | ||
106 | 144 | | |||
107 | void FlatpakTransaction::onRuntimeJobFinished() | 145 | void FlatpakTransaction::onJobFinished() | ||
108 | { | 146 | { | ||
109 | m_runtimeJobProgress = 100; | 147 | FlatpakTransactionJob *job = static_cast<FlatpakTransactionJob*>(sender()); | ||
110 | 148 | | |||
111 | updateProgress(); | 149 | if (job != m_appJob) { | ||
150 | if (!job->result()) { | ||||
151 | Q_EMIT passiveMessage(job->errorMessage()); | ||||
152 | } | ||||
112 | 153 | | |||
113 | if (!m_runtimeJob->result()) { | 154 | // Mark runtime as installed | ||
114 | Q_EMIT passiveMessage(m_runtimeJob->errorMessage()); | 155 | if (m_runtime && job->app()->flatpakName() == m_runtime->flatpakName() && !job->isRelated() && role() != Transaction::Role::RemoveRole) { | ||
115 | } else { | 156 | if (job->result()) { | ||
116 | // This should be the only case when runtime is automatically installed, but better to check | | |||
117 | if (role() == InstallRole) { | | |||
118 | m_runtime->setState(AbstractResource::Installed); | 157 | m_runtime->setState(AbstractResource::Installed); | ||
119 | } | 158 | } | ||
120 | } | 159 | } | ||
160 | } | ||||
121 | 161 | | |||
122 | if (m_appJob->isFinished()) { | 162 | foreach (const QPointer<FlatpakTransactionJob> &job, m_jobs) { | ||
123 | finishTransaction(); | 163 | if (job->isRunning()) { | ||
164 | return; | ||||
124 | } | 165 | } | ||
125 | } | 166 | } | ||
126 | 167 | | |||
127 | void FlatpakTransaction::onRuntimeJobProgressChanged(int progress) | 168 | // No other job is running → finish transaction | ||
128 | { | 169 | finishTransaction(); | ||
129 | m_runtimeJobProgress = progress; | | |||
130 | | ||||
131 | updateProgress(); | | |||
132 | } | 170 | } | ||
133 | 171 | | |||
134 | void FlatpakTransaction::updateProgress() | 172 | void FlatpakTransaction::onJobProgressChanged(int progress) | ||
135 | { | 173 | { | ||
136 | if (m_runtime) { | 174 | Q_UNUSED(progress); | ||
137 | setProgress((m_appJobProgress + m_runtimeJobProgress) / 2); | 175 | | ||
138 | } else { | 176 | int total = 0; | ||
139 | setProgress(m_appJobProgress); | 177 | | ||
178 | // Count progress from all the jobs | ||||
179 | foreach (const QPointer<FlatpakTransactionJob> &job, m_jobs) { | ||||
180 | total += job->progress(); | ||||
140 | } | 181 | } | ||
182 | | ||||
183 | setProgress(total / m_jobs.count()); | ||||
141 | } | 184 | } | ||
142 | 185 | | |||
143 | void FlatpakTransaction::finishTransaction() | 186 | void FlatpakTransaction::finishTransaction() | ||
144 | { | 187 | { | ||
145 | if (m_appJob->result()) { | 188 | if (m_appJob->result()) { | ||
146 | AbstractResource::State newState = AbstractResource::None; | 189 | AbstractResource::State newState = AbstractResource::None; | ||
147 | switch(role()) { | 190 | switch(role()) { | ||
148 | case InstallRole: | 191 | case InstallRole: | ||
Show All 15 Lines |