summaryrefslogtreecommitdiffstats
path: root/plugins/dpkg
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--plugins/dpkg/gs-plugin-dpkg.c133
-rw-r--r--plugins/dpkg/gs-plugin-dpkg.h22
-rw-r--r--plugins/dpkg/gs-self-test.c87
-rw-r--r--plugins/dpkg/meson.build35
-rwxr-xr-xplugins/dpkg/tests/build-deb.sh1
-rw-r--r--plugins/dpkg/tests/chiron-1.1-1.debbin0 -> 806 bytes
-rw-r--r--plugins/dpkg/tests/debian/DEBIAN/control13
-rw-r--r--plugins/dpkg/tests/debian/usr/bin/chiron0
8 files changed, 291 insertions, 0 deletions
diff --git a/plugins/dpkg/gs-plugin-dpkg.c b/plugins/dpkg/gs-plugin-dpkg.c
new file mode 100644
index 0000000..3f886e0
--- /dev/null
+++ b/plugins/dpkg/gs-plugin-dpkg.c
@@ -0,0 +1,133 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2011-2013 Richard Hughes <richard@hughsie.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <gnome-software.h>
+
+#include "gs-plugin-dpkg.h"
+
+struct _GsPluginDpkg
+{
+ GsPlugin parent;
+};
+
+G_DEFINE_TYPE (GsPluginDpkg, gs_plugin_dpkg, GS_TYPE_PLUGIN)
+
+#define DPKG_DEB_BINARY "/usr/bin/dpkg-deb"
+
+static void
+gs_plugin_dpkg_init (GsPluginDpkg *self)
+{
+ GsPlugin *plugin = GS_PLUGIN (self);
+
+ if (!g_file_test (DPKG_DEB_BINARY, G_FILE_TEST_EXISTS)) {
+ g_debug ("disabling '%s' as no %s available",
+ gs_plugin_get_name (plugin), DPKG_DEB_BINARY);
+ gs_plugin_set_enabled (plugin, FALSE);
+ }
+}
+
+gboolean
+gs_plugin_file_to_app (GsPlugin *plugin,
+ GsAppList *list,
+ GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ guint i;
+ g_autofree gchar *content_type = NULL;
+ g_autofree gchar *output = NULL;
+ g_auto(GStrv) argv = NULL;
+ g_auto(GStrv) tokens = NULL;
+ g_autoptr(GsApp) app = NULL;
+ g_autoptr(GString) str = NULL;
+ const gchar *mimetypes[] = {
+ "application/vnd.debian.binary-package",
+ NULL };
+
+ /* does this match any of the mimetypes we support */
+ content_type = gs_utils_get_content_type (file, cancellable, error);
+ if (content_type == NULL)
+ return FALSE;
+ if (!g_strv_contains (mimetypes, content_type))
+ return TRUE;
+
+ /* exec sync */
+ argv = g_new0 (gchar *, 5);
+ argv[0] = g_strdup (DPKG_DEB_BINARY);
+ argv[1] = g_strdup ("--showformat=${Package}\\n"
+ "${Version}\\n"
+ "${Installed-Size}\\n"
+ "${Homepage}\\n"
+ "${Description}");
+ argv[2] = g_strdup ("-W");
+ argv[3] = g_file_get_path (file);
+ if (!g_spawn_sync (NULL, argv, NULL,
+ G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL,
+ NULL, NULL, &output, NULL, NULL, error)) {
+ gs_utils_error_convert_gio (error);
+ return FALSE;
+ }
+
+ /* parse output */
+ tokens = g_strsplit (output, "\n", 0);
+ if (g_strv_length (tokens) < 5) {
+ g_set_error (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_NOT_SUPPORTED,
+ "dpkg-deb output format incorrect:\n\"%s\"\n", output);
+ return FALSE;
+ }
+
+ /* create app */
+ app = gs_app_new (NULL);
+ gs_app_set_state (app, GS_APP_STATE_AVAILABLE_LOCAL);
+ gs_app_add_source (app, tokens[0]);
+ gs_app_set_name (app, GS_APP_QUALITY_LOWEST, tokens[0]);
+ gs_app_set_version (app, tokens[1]);
+ gs_app_set_size_installed (app, GS_SIZE_TYPE_VALID, 1024 * g_ascii_strtoull (tokens[2], NULL, 10));
+ gs_app_set_url (app, AS_URL_KIND_HOMEPAGE, tokens[3]);
+ gs_app_set_summary (app, GS_APP_QUALITY_LOWEST, tokens[4]);
+ gs_app_set_kind (app, AS_COMPONENT_KIND_GENERIC);
+ gs_app_set_bundle_kind (app, AS_BUNDLE_KIND_PACKAGE);
+ gs_app_set_metadata (app, "GnomeSoftware::Creator",
+ gs_plugin_get_name (plugin));
+
+ /* multiline text */
+ str = g_string_new ("");
+ for (i = 5; tokens[i] != NULL; i++) {
+ if (g_strcmp0 (tokens[i], " .") == 0) {
+ if (str->len > 0)
+ g_string_truncate (str, str->len - 1);
+ g_string_append (str, "\n");
+ continue;
+ }
+ g_strstrip (tokens[i]);
+ g_string_append_printf (str, "%s ", tokens[i]);
+ }
+ if (str->len > 0)
+ g_string_truncate (str, str->len - 1);
+ gs_app_set_description (app, GS_APP_QUALITY_LOWEST, str->str);
+
+ /* success */
+ gs_app_list_add (list, app);
+ return TRUE;
+}
+
+static void
+gs_plugin_dpkg_class_init (GsPluginDpkgClass *klass)
+{
+}
+
+GType
+gs_plugin_query_type (void)
+{
+ return GS_TYPE_PLUGIN_DPKG;
+}
diff --git a/plugins/dpkg/gs-plugin-dpkg.h b/plugins/dpkg/gs-plugin-dpkg.h
new file mode 100644
index 0000000..df16fde
--- /dev/null
+++ b/plugins/dpkg/gs-plugin-dpkg.h
@@ -0,0 +1,22 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2021 Endless OS Foundation LLC
+ *
+ * Author: Philip Withnall <pwithnall@endlessos.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#pragma once
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_PLUGIN_DPKG (gs_plugin_dpkg_get_type ())
+
+G_DECLARE_FINAL_TYPE (GsPluginDpkg, gs_plugin_dpkg, GS, PLUGIN_DPKG, GsPlugin)
+
+G_END_DECLS
diff --git a/plugins/dpkg/gs-self-test.c b/plugins/dpkg/gs-self-test.c
new file mode 100644
index 0000000..ecb567d
--- /dev/null
+++ b/plugins/dpkg/gs-self-test.c
@@ -0,0 +1,87 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2013-2017 Richard Hughes <richard@hughsie.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "config.h"
+
+#include "gnome-software-private.h"
+
+#include "gs-test.h"
+
+static void
+gs_plugins_dpkg_func (GsPluginLoader *plugin_loader)
+{
+ g_autoptr(GsApp) app = NULL;
+ g_autoptr(GsPluginJob) plugin_job = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *fn = NULL;
+ g_autoptr(GFile) file = NULL;
+
+ /* no dpkg, abort */
+ if (!gs_plugin_loader_get_enabled (plugin_loader, "dpkg")) {
+ g_test_skip ("not enabled");
+ return;
+ }
+
+ /* load local file */
+ fn = gs_test_get_filename (TESTDATADIR, "chiron-1.1-1.deb");
+ g_assert (fn != NULL);
+ file = g_file_new_for_path (fn);
+ plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_FILE_TO_APP,
+ "file", file,
+ NULL);
+ app = gs_plugin_loader_job_process_app (plugin_loader, plugin_job, NULL, &error);
+ gs_test_flush_main_context ();
+ g_assert_no_error (error);
+ g_assert (app != NULL);
+ g_assert_cmpstr (gs_app_get_source_default (app), ==, "chiron");
+ g_assert_cmpstr (gs_app_get_url (app, AS_URL_KIND_HOMEPAGE), ==, "http://127.0.0.1/");
+ g_assert_cmpstr (gs_app_get_name (app), ==, "chiron");
+ g_assert_cmpstr (gs_app_get_version (app), ==, "1.1-1");
+ g_assert_cmpstr (gs_app_get_summary (app), ==, "Single line synopsis");
+ g_assert_cmpstr (gs_app_get_description (app), ==,
+ "This is the first paragraph in the example "
+ "package control file.\nThis is the second paragraph.");
+ g_assert (gs_app_get_local_file (app) != NULL);
+}
+
+int
+main (int argc, char **argv)
+{
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GsPluginLoader) plugin_loader = NULL;
+ const gchar * const allowlist[] = {
+ "dpkg",
+ NULL
+ };
+
+ /* While we use %G_TEST_OPTION_ISOLATE_DIRS to create temporary directories
+ * for each of the tests, we want to use the system MIME registry, assuming
+ * that it exists and correctly has shared-mime-info installed. */
+ g_content_type_set_mime_dirs (NULL);
+
+ gs_test_init (&argc, &argv);
+
+ /* we can only load this once per process */
+ plugin_loader = gs_plugin_loader_new (NULL, NULL);
+ gs_plugin_loader_add_location (plugin_loader, LOCALPLUGINDIR);
+ ret = gs_plugin_loader_setup (plugin_loader,
+ allowlist,
+ NULL,
+ NULL,
+ &error);
+ g_assert_no_error (error);
+ g_assert (ret);
+
+ /* plugin tests go here */
+ g_test_add_data_func ("/gnome-software/plugins/dpkg",
+ plugin_loader,
+ (GTestDataFunc) gs_plugins_dpkg_func);
+
+ return g_test_run ();
+}
diff --git a/plugins/dpkg/meson.build b/plugins/dpkg/meson.build
new file mode 100644
index 0000000..594d6e4
--- /dev/null
+++ b/plugins/dpkg/meson.build
@@ -0,0 +1,35 @@
+cargs = ['-DG_LOG_DOMAIN="GsPluginDpkg"']
+
+shared_module(
+ 'gs_plugin_dpkg',
+ sources : 'gs-plugin-dpkg.c',
+ include_directories : [
+ include_directories('../..'),
+ include_directories('../../lib'),
+ ],
+ install : true,
+ install_dir: plugin_dir,
+ c_args : cargs,
+ dependencies : plugin_libs,
+)
+
+if get_option('tests')
+ cargs += ['-DLOCALPLUGINDIR="' + meson.current_build_dir() + '"']
+ cargs += ['-DTESTDATADIR="' + join_paths(meson.current_source_dir(), 'tests') + '"']
+ e = executable(
+ 'gs-self-test-dpkg',
+ compiled_schemas,
+ sources : [
+ 'gs-self-test.c'
+ ],
+ include_directories : [
+ include_directories('../..'),
+ include_directories('../../lib'),
+ ],
+ dependencies : [
+ plugin_libs,
+ ],
+ c_args : cargs,
+ )
+ test('gs-self-test-dpkg', e, suite: ['plugins', 'dpkg'], env: test_env)
+endif
diff --git a/plugins/dpkg/tests/build-deb.sh b/plugins/dpkg/tests/build-deb.sh
new file mode 100755
index 0000000..cbf50f6
--- /dev/null
+++ b/plugins/dpkg/tests/build-deb.sh
@@ -0,0 +1 @@
+dpkg-deb --build debian chiron-1.1-1.deb
diff --git a/plugins/dpkg/tests/chiron-1.1-1.deb b/plugins/dpkg/tests/chiron-1.1-1.deb
new file mode 100644
index 0000000..f4f921a
--- /dev/null
+++ b/plugins/dpkg/tests/chiron-1.1-1.deb
Binary files differ
diff --git a/plugins/dpkg/tests/debian/DEBIAN/control b/plugins/dpkg/tests/debian/DEBIAN/control
new file mode 100644
index 0000000..ad5d9c6
--- /dev/null
+++ b/plugins/dpkg/tests/debian/DEBIAN/control
@@ -0,0 +1,13 @@
+Package: chiron
+Version: 1.1-1
+Section: base
+Priority: optional
+Architecture: all
+Homepage: http://127.0.0.1/
+Maintainer: Richard Hughes <richard@hughsie.com>
+Description: Single line synopsis
+ This is the first
+ paragraph in the example package
+ control file.
+ .
+ This is the second paragraph.
diff --git a/plugins/dpkg/tests/debian/usr/bin/chiron b/plugins/dpkg/tests/debian/usr/bin/chiron
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/dpkg/tests/debian/usr/bin/chiron