summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Grulich <[email protected]>2017-03-07 13:37:24 +0100
committerJan Grulich <[email protected]>2017-03-07 13:37:24 +0100
commitc1bd05a1bd3fb79a2c6b76ba9343fa6ac65091c3 (patch)
treed2df83ef5905e1a0fdbe11fe37e8333d2e0fd860
parent3928d93109f91f571b8f1e6707762e0a46bcf576 (diff)
Add support for .flatpakrepo files
-rw-r--r--libdiscover/backends/FlatpakBackend/FlatpakBackend.cpp77
-rw-r--r--libdiscover/backends/FlatpakBackend/FlatpakBackend.h3
-rw-r--r--libdiscover/backends/FlatpakBackend/FlatpakResource.cpp12
-rw-r--r--libdiscover/backends/FlatpakBackend/FlatpakResource.h6
-rw-r--r--libdiscover/backends/FlatpakBackend/FlatpakSourcesBackend.cpp51
-rw-r--r--libdiscover/backends/FlatpakBackend/FlatpakSourcesBackend.h3
-rw-r--r--libdiscover/backends/FlatpakBackend/org.kde.discover-flatpak.desktop2
7 files changed, 147 insertions, 7 deletions
diff --git a/libdiscover/backends/FlatpakBackend/FlatpakBackend.cpp b/libdiscover/backends/FlatpakBackend/FlatpakBackend.cpp
index cfacd74..0ba8822 100644
--- a/libdiscover/backends/FlatpakBackend/FlatpakBackend.cpp
+++ b/libdiscover/backends/FlatpakBackend/FlatpakBackend.cpp
@@ -85,7 +85,8 @@ FlatpakBackend::FlatpakBackend(QObject* parent)
m_messageActions = QList<QAction*>() << updateAction;
- SourcesModel::global()->addSourcesBackend(new FlatpakSourcesBackend(m_flatpakInstallationSystem, m_flatpakInstallationUser, this));
+ m_sources = new FlatpakSourcesBackend(m_flatpakInstallationSystem, m_flatpakInstallationUser, this);
+ SourcesModel::global()->addSourcesBackend(m_sources);
}
FlatpakBackend::~FlatpakBackend()
@@ -370,6 +371,54 @@ FlatpakResource * FlatpakBackend::addAppFromFlatpakRef(const QUrl &url)
return resource;
}
+FlatpakResource * FlatpakBackend::addSourceFromFlatpakRepo(const QUrl &url)
+{
+ QSettings settings(url.toLocalFile(), QSettings::NativeFormat);
+
+ const QString gpgKey = settings.value(QStringLiteral("Flatpak Repo/GPGKey")).toString();
+ const QString title = settings.value(QStringLiteral("Flatpak Repo/Title")).toString();
+ const QString repoUrl = settings.value(QStringLiteral("Flatpak Repo/Url")).toString();
+
+ if (gpgKey.isEmpty() || title.isEmpty() || repoUrl.isEmpty()) {
+ return nullptr;
+ }
+
+ if (gpgKey.startsWith(QStringLiteral("http://")) || gpgKey.startsWith(QStringLiteral("https://"))) {
+ return nullptr;
+ }
+
+ AsComponent *component = as_component_new();
+ as_component_add_url(component, AS_URL_KIND_HOMEPAGE, settings.value(QStringLiteral("Flatpak Repo/Homepage")).toString().toStdString().c_str());
+ as_component_set_summary(component, settings.value(QStringLiteral("Flatpak Repo/Comment")).toString().toStdString().c_str(), nullptr);
+ as_component_set_description(component, settings.value(QStringLiteral("Flatpak Repo/Description")).toString().toStdString().c_str(), nullptr);
+ as_component_set_name(component, title.toStdString().c_str(), nullptr);
+ const QString iconUrl = settings.value(QStringLiteral("Flatpak Ref/Icon")).toString();
+ if (!iconUrl.isEmpty()) {
+ AsIcon *icon = as_icon_new();
+ as_icon_set_kind(icon, AS_ICON_KIND_REMOTE);
+ as_icon_set_url(icon, iconUrl.toStdString().c_str());
+ as_component_add_icon(component, icon);
+ }
+
+ AppStream::Component *asComponent = new AppStream::Component(component);
+ auto resource = new FlatpakResource(asComponent, this);
+ // Use metadata only for stuff which are not common for all resources
+ resource->addMetadata(QStringLiteral("gpg-key"), gpgKey);
+ resource->addMetadata(QStringLiteral("repo-url"), repoUrl);
+ resource->setBranch(settings.value(QStringLiteral("Flatpak Repo/DefaultBranch")).toString());
+ resource->setFlatpakName(url.fileName().remove(QStringLiteral(".flatpakrepo")));
+ resource->setType(FlatpakResource::Source);
+
+ auto repo = flatpak_installation_get_remote_by_name(m_flatpakInstallationSystem, resource->flatpakName().toStdString().c_str(), m_cancellable, nullptr);
+ if (!repo) {
+ resource->setState(AbstractResource::State::None);
+ } else {
+ resource->setState(AbstractResource::State::Installed);
+ }
+
+ return resource;
+}
+
void FlatpakBackend::addResource(FlatpakResource *resource)
{
// Update app with all possible information we have
@@ -947,8 +996,19 @@ FlatpakInstallation * FlatpakBackend::flatpakInstallationForAppScope(FlatpakReso
void FlatpakBackend::installApplication(AbstractResource *app, const AddonList &addons)
{
- FlatpakTransaction *transaction = nullptr;
FlatpakResource *resource = qobject_cast<FlatpakResource*>(app);
+
+ if (resource->type() == FlatpakResource::Source) {
+ // Let source backend handle this
+ FlatpakRemote *remote = m_sources->installSource(resource);
+ if (remote) {
+ resource->setState(AbstractResource::Installed);
+ integrateRemote(m_flatpakInstallationSystem, remote);
+ }
+ return;
+ }
+
+ FlatpakTransaction *transaction = nullptr;
FlatpakInstallation *installation = resource->scope() == FlatpakResource::System ? m_flatpakInstallationSystem : m_flatpakInstallationUser;
FlatpakResource *runtime = getRuntimeForApp(resource);
@@ -973,6 +1033,15 @@ void FlatpakBackend::installApplication(AbstractResource *app)
void FlatpakBackend::removeApplication(AbstractResource *app)
{
FlatpakResource *resource = qobject_cast<FlatpakResource*>(app);
+
+ if (resource->type() == FlatpakResource::Source) {
+ // Let source backend handle this
+ if (m_sources->removeSource(resource->flatpakName())) {
+ resource->setState(AbstractResource::None);
+ }
+ return;
+ }
+
FlatpakInstallation *installation = resource->scope() == FlatpakResource::System ? m_flatpakInstallationSystem : m_flatpakInstallationUser;
FlatpakTransaction *transaction = new FlatpakTransaction(installation, resource, Transaction::RemoveRole);
@@ -996,7 +1065,7 @@ void FlatpakBackend::checkForUpdates()
AbstractResource * FlatpakBackend::resourceForFile(const QUrl &url)
{
- if ((!url.path().endsWith(QLatin1String(".flatpakref")) && !url.path().endsWith(QLatin1String(".flatpak"))) || !url.isLocalFile()) {
+ if ((!url.path().endsWith(QLatin1String(".flatpakref")) && !url.path().endsWith(QLatin1String(".flatpak")) && !url.path().endsWith(QLatin1String(".flatpakrepo"))) || !url.isLocalFile()) {
return nullptr;
}
@@ -1006,7 +1075,7 @@ AbstractResource * FlatpakBackend::resourceForFile(const QUrl &url)
} else if (url.path().endsWith(QLatin1String(".flatpakref"))) {
resource = addAppFromFlatpakRef(url);
} else {
- // TODO .flatpakrepo
+ resource = addSourceFromFlatpakRepo(url);
}
return resource;
diff --git a/libdiscover/backends/FlatpakBackend/FlatpakBackend.h b/libdiscover/backends/FlatpakBackend/FlatpakBackend.h
index 6b28e5c..1b69d11 100644
--- a/libdiscover/backends/FlatpakBackend/FlatpakBackend.h
+++ b/libdiscover/backends/FlatpakBackend/FlatpakBackend.h
@@ -34,6 +34,7 @@ extern "C" {
}
class QAction;
+class FlatpakSourcesBackend;
class FlatpakReviewsBackend;
class StandardBackendUpdater;
class FlatpakBackend : public AbstractResourcesBackend
@@ -76,6 +77,7 @@ private:
FlatpakResource * addAppFromFlatpakBundle(const QUrl &url);
FlatpakResource * addAppFromFlatpakRef(const QUrl &url);
+ FlatpakResource * addSourceFromFlatpakRepo(const QUrl &url);
void addResource(FlatpakResource *resource);
bool compareAppFlatpakRef(FlatpakInstallation *flatpakInstallation, FlatpakResource *resource, FlatpakInstalledRef *ref);
bool loadAppsFromAppstreamData(FlatpakInstallation *flatpakInstallation);
@@ -95,6 +97,7 @@ private:
QHash<QString, FlatpakResource*> m_resources;
StandardBackendUpdater *m_updater;
+ FlatpakSourcesBackend *m_sources;
FlatpakReviewsBackend *m_reviews;
bool m_fetching;
QList<QAction*> m_messageActions;
diff --git a/libdiscover/backends/FlatpakBackend/FlatpakResource.cpp b/libdiscover/backends/FlatpakBackend/FlatpakResource.cpp
index 12fe5a8..0c2940b 100644
--- a/libdiscover/backends/FlatpakBackend/FlatpakResource.cpp
+++ b/libdiscover/backends/FlatpakBackend/FlatpakResource.cpp
@@ -86,7 +86,7 @@ QString FlatpakResource::branch() const
bool FlatpakResource::canExecute() const
{
- return (m_state == AbstractResource::Installed || m_state == AbstractResource::Upgradeable);
+ return (m_type == DesktopApp && (m_state == AbstractResource::Installed || m_state == AbstractResource::Upgradeable));
}
void FlatpakResource::updateFromRef(FlatpakRef* ref)
@@ -237,6 +237,11 @@ QString FlatpakResource::name()
return name;
}
+QVariant FlatpakResource::metadata(const QString &key)
+{
+ return m_metadata.value(key);
+}
+
QString FlatpakResource::origin() const
{
return m_origin;
@@ -393,6 +398,11 @@ void FlatpakResource::fetchScreenshots()
Q_EMIT screenshotsFetched(thumbnails, screenshots);
}
+void FlatpakResource::addMetadata(const QString &key, const QVariant &value)
+{
+ m_metadata.insert(key, value);
+}
+
void FlatpakResource::setArch(const QString &arch)
{
m_arch = arch;
diff --git a/libdiscover/backends/FlatpakBackend/FlatpakResource.h b/libdiscover/backends/FlatpakBackend/FlatpakResource.h
index 171b1e8..ef79d64 100644
--- a/libdiscover/backends/FlatpakBackend/FlatpakResource.h
+++ b/libdiscover/backends/FlatpakBackend/FlatpakResource.h
@@ -42,7 +42,8 @@ public:
enum ResourceType {
DesktopApp = 0,
- Runtime
+ Runtime,
+ Source
};
enum Scope {
@@ -88,6 +89,7 @@ public:
QString license() override;
QString longDescription() override;
QString name() override;
+ QVariant metadata(const QString &key);
QString origin() const override;
QString packageName() const override;
QUrl resourceFile() const;
@@ -107,6 +109,7 @@ public:
void fetchChangelog() override;
void fetchScreenshots() override;
+ void addMetadata(const QString &key, const QVariant &value);
void setArch(const QString &arch);
void setBranch(const QString &branch);
void setBundledIcon(const QPixmap &pixmap);
@@ -140,6 +143,7 @@ public:
QString m_flatpakName;
QString m_iconPath;
int m_installedSize;
+ QVariantMap m_metadata;
QString m_origin;
QUrl m_resourceFile;
QString m_runtime;
diff --git a/libdiscover/backends/FlatpakBackend/FlatpakSourcesBackend.cpp b/libdiscover/backends/FlatpakBackend/FlatpakSourcesBackend.cpp
index 1092398..793d928 100644
--- a/libdiscover/backends/FlatpakBackend/FlatpakSourcesBackend.cpp
+++ b/libdiscover/backends/FlatpakBackend/FlatpakSourcesBackend.cpp
@@ -20,6 +20,7 @@
***************************************************************************/
#include "FlatpakSourcesBackend.h"
+#include "FlatpakResource.h"
#include <QDebug>
@@ -38,6 +39,7 @@ private:
FlatpakSourcesBackend::FlatpakSourcesBackend(FlatpakInstallation *systemInstallation, FlatpakInstallation *userInstallation, QObject* parent)
: AbstractSourcesBackend(parent)
+ , m_systemInstallation(systemInstallation)
, m_sources(new QStandardItemModel(this))
{
QHash<int, QByteArray> roles = m_sources->roleNames();
@@ -120,3 +122,52 @@ bool FlatpakSourcesBackend::listRepositories(FlatpakInstallation* installation)
return true;
}
+
+FlatpakRemote * FlatpakSourcesBackend::installSource(FlatpakResource *resource)
+{
+ g_autoptr(GCancellable) cancellable = g_cancellable_new();
+
+ auto remote = flatpak_installation_get_remote_by_name(m_systemInstallation, resource->flatpakName().toStdString().c_str(), cancellable, nullptr);
+ if (remote) {
+ qWarning() << "Source " << resource->flatpakName() << " already exists";
+ return nullptr;
+ }
+
+ remote = flatpak_remote_new(resource->flatpakName().toStdString().c_str());
+ flatpak_remote_set_url(remote, resource->metadata(QStringLiteral("repo-url")).toString().toStdString().c_str());
+ flatpak_remote_set_noenumerate(remote, false);
+ flatpak_remote_set_title(remote, resource->comment().toStdString().c_str());
+
+ const QString gpgKey = resource->metadata(QStringLiteral("gpg-key")).toString();
+ if (!gpgKey.isEmpty()) {
+ gsize dataLen = 0;
+ g_autofree guchar *data = nullptr;
+ g_autoptr(GBytes) bytes = nullptr;
+ data = g_base64_decode(gpgKey.toStdString().c_str(), &dataLen);
+ bytes = g_bytes_new(data, dataLen);
+ flatpak_remote_set_gpg_verify(remote, true);
+ flatpak_remote_set_gpg_key(remote, bytes);
+ } else {
+ flatpak_remote_set_gpg_verify(remote, false);
+ }
+
+ if (!resource->branch().isEmpty()) {
+ flatpak_remote_set_default_branch(remote, resource->branch().toStdString().c_str());
+ }
+
+ if (!flatpak_installation_modify_remote(m_systemInstallation, remote, cancellable, nullptr)) {
+ qWarning() << "Failed to add source " << resource->flatpakName();
+ return nullptr;
+ }
+
+ FlatpakSourceItem *it = new FlatpakSourceItem(resource->flatpakName());
+ it->setCheckState(flatpak_remote_get_disabled(remote) ? Qt::Unchecked : Qt::Checked);
+ it->setData(resource->comment().isEmpty() ? resource->flatpakName() : resource->comment(), Qt::ToolTipRole);
+ it->setData(name(), AbstractSourcesBackend::SectionRole);
+ it->setData(QVariant::fromValue<QObject*>(this), AbstractSourcesBackend::SourcesBackend);
+ it->setFlatpakInstallation(m_systemInstallation);
+
+ m_sources->appendRow(it);
+
+ return remote;
+}
diff --git a/libdiscover/backends/FlatpakBackend/FlatpakSourcesBackend.h b/libdiscover/backends/FlatpakBackend/FlatpakSourcesBackend.h
index c79eff8..9631a50 100644
--- a/libdiscover/backends/FlatpakBackend/FlatpakSourcesBackend.h
+++ b/libdiscover/backends/FlatpakBackend/FlatpakSourcesBackend.h
@@ -29,6 +29,7 @@ extern "C" {
#include <flatpak.h>
}
+class FlatpakResource;
class FlatpakSourcesBackend : public AbstractSourcesBackend
{
public:
@@ -41,9 +42,11 @@ public:
QString idDescription() override { return QStringLiteral("Flatpak remote repositories"); }
QList<QAction*> actions() const override;
+ FlatpakRemote * installSource(FlatpakResource *resource);
private:
bool listRepositories(FlatpakInstallation *installation);
+ FlatpakInstallation *m_systemInstallation;
QStandardItemModel* m_sources;
QAction* m_testAction;
};
diff --git a/libdiscover/backends/FlatpakBackend/org.kde.discover-flatpak.desktop b/libdiscover/backends/FlatpakBackend/org.kde.discover-flatpak.desktop
index 391b3bf..9b8a3ae 100644
--- a/libdiscover/backends/FlatpakBackend/org.kde.discover-flatpak.desktop
+++ b/libdiscover/backends/FlatpakBackend/org.kde.discover-flatpak.desktop
@@ -44,4 +44,4 @@ Type=Application
X-DocPath=plasma-discover/index.html
Categories=Qt;KDE;System;
-MimeType=application/vnd.flatpak.ref;application/vnd.flatpak
+MimeType=application/vnd.flatpak.ref;application/vnd.flatpak;application/vnd.flatpak.repo