[gnome-shell] extensions-tool: Add 'install' command
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] extensions-tool: Add 'install' command
- Date: Wed, 21 Aug 2019 16:39:32 +0000 (UTC)
commit a429fdbd081722f079b0452df37abc97f396ee5f
Author: Florian Müllner <fmuellner gnome org>
Date: Tue Sep 4 01:41:55 2018 +0200
extensions-tool: Add 'install' command
The ability to install unaudited extensions directly from a zip file
can be useful for testing and code review, so implement a corresponding
command that complements the previously added 'pack' command.
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1234
src/extensions-tool/command-install.c | 207 +++++++++++++++++++++
src/extensions-tool/command-pack.c | 24 +--
src/extensions-tool/commands.h | 1 +
src/extensions-tool/common.h | 3 +
.../completion/bash/gnome-extensions | 9 +-
src/extensions-tool/main.c | 28 +++
src/extensions-tool/man/gnome-extensions.txt | 18 ++
src/extensions-tool/meson-src.build | 1 +
src/extensions-tool/meson.build | 1 +
9 files changed, 268 insertions(+), 24 deletions(-)
---
diff --git a/src/extensions-tool/command-install.c b/src/extensions-tool/command-install.c
new file mode 100644
index 0000000000..58f62bb866
--- /dev/null
+++ b/src/extensions-tool/command-install.c
@@ -0,0 +1,207 @@
+/* command-install.c
+ *
+ * Copyright 2018 Florian Müllner <fmuellner gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include <gnome-autoar/gnome-autoar.h>
+#include <json-glib/json-glib.h>
+
+#include "commands.h"
+#include "common.h"
+#include "config.h"
+
+static JsonObject *
+load_metadata (GFile *dir,
+ GError **error)
+{
+ g_autoptr (JsonParser) parser = NULL;
+ g_autoptr (GInputStream) stream = NULL;
+ g_autoptr (GFile) file = NULL;
+
+ file = g_file_get_child (dir, "metadata.json");
+ stream = G_INPUT_STREAM (g_file_read (file, NULL, error));
+ if (stream == NULL)
+ return NULL;
+
+ parser = json_parser_new_immutable ();
+ if (!json_parser_load_from_stream (parser, stream, NULL, error))
+ return NULL;
+
+ return json_node_dup_object (json_parser_get_root (parser));
+}
+
+static void
+on_error (AutoarExtractor *extractor,
+ GError *error,
+ gpointer data)
+{
+ *((GError **)data) = g_error_copy (error);
+}
+
+static GFile *
+on_decide_destination (AutoarExtractor *extractor,
+ GFile *dest,
+ GList *files,
+ gpointer data)
+{
+ g_autofree char *dest_path = NULL;
+ GFile *new_dest;
+ int copy = 1;
+
+ dest_path = g_file_get_path (dest);
+ new_dest = g_object_ref (dest);
+
+ while (g_file_query_exists (new_dest, NULL))
+ {
+ g_autofree char *new_path = g_strdup_printf ("%s (%d)", dest_path, copy);
+
+ g_object_unref (new_dest);
+ new_dest = g_file_new_for_path (new_path);
+
+ copy++;
+ }
+
+ *((GFile **)data) = g_object_ref (new_dest);
+
+ return new_dest;
+}
+
+static int
+install_extension (const char *bundle,
+ gboolean force)
+{
+ g_autoptr (AutoarExtractor) extractor = NULL;
+ g_autoptr (JsonObject) metadata = NULL;
+ g_autoptr (GFile) cachedir = NULL;
+ g_autoptr (GFile) tmpdir = NULL;
+ g_autoptr (GFile) src = NULL;
+ g_autoptr (GFile) dst = NULL;
+ g_autoptr (GFile) dstdir = NULL;
+ g_autoptr (GError) error = NULL;
+ g_autofree char *cwd = NULL;
+ const char *uuid;
+
+ cwd = g_get_current_dir ();
+ src = g_file_new_for_commandline_arg_and_cwd (bundle, cwd);
+ cachedir = g_file_new_for_path (g_get_user_cache_dir ());
+
+ extractor = autoar_extractor_new (src, cachedir);
+
+ g_signal_connect (extractor, "error", G_CALLBACK (on_error), &error);
+ g_signal_connect (extractor, "decide-destination", G_CALLBACK (on_decide_destination), &tmpdir);
+
+ autoar_extractor_start (extractor, NULL);
+
+ if (error != NULL)
+ goto err;
+
+ metadata = load_metadata (tmpdir, &error);
+ if (metadata == NULL)
+ goto err;
+
+ dstdir = g_file_new_build_filename (g_get_user_data_dir (),
+ "gnome-shell", "extensions", NULL);
+
+ if (!g_file_make_directory_with_parents (dstdir, NULL, &error))
+ goto err;
+
+ uuid = json_object_get_string_member (metadata, "uuid");
+ dst = g_file_get_child (dstdir, uuid);
+
+ if (g_file_query_exists (dst, NULL))
+ {
+ if (!force)
+ {
+ g_set_error (&error, G_IO_ERROR, G_IO_ERROR_EXISTS,
+ "%s exists and --force was not specified", uuid);
+ goto err;
+ }
+ else if (!file_delete_recursively (dst, &error))
+ {
+ goto err;
+ }
+ }
+
+ if (!g_file_move (tmpdir, dst, G_FILE_COPY_NONE, NULL, NULL, NULL, &error))
+ goto err;
+
+ return 0;
+
+err:
+ if (error != NULL)
+ g_printerr ("%s\n", error->message);
+
+ if (tmpdir != NULL)
+ file_delete_recursively (tmpdir, NULL);
+
+ return 2;
+}
+
+int
+handle_install (int argc, char *argv[], gboolean do_help)
+{
+ g_autoptr (GOptionContext) context = NULL;
+ g_autoptr (GError) error = NULL;
+ g_auto (GStrv) filenames = NULL;
+ gboolean force = FALSE;
+ GOptionEntry entries[] = {
+ { .long_name = "force", .short_name = 'f',
+ .arg = G_OPTION_ARG_NONE, .arg_data = &force,
+ .description = _("Overwrite an existing extension") },
+ { .long_name = G_OPTION_REMAINING,
+ .arg_description =_("EXTENSION_BUNDLE"),
+ .arg = G_OPTION_ARG_FILENAME_ARRAY, .arg_data = &filenames },
+ { NULL }
+ };
+
+ g_set_prgname ("gnome-extensions install");
+
+ context = g_option_context_new (NULL);
+ g_option_context_set_help_enabled (context, FALSE);
+ g_option_context_set_summary (context, _("Install an extension bundle"));
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+
+ if (do_help)
+ {
+ show_help (context, NULL);
+ return 0;
+ }
+
+ if (!g_option_context_parse (context, &argc, &argv, &error))
+ {
+ show_help (context, error->message);
+ return 1;
+ }
+
+ if (filenames == NULL)
+ {
+ show_help (context, _("No extension bundle specified"));
+ return 1;
+ }
+
+ if (g_strv_length (filenames) > 1)
+ {
+ show_help (context, _("More than one extension bundle specified"));
+ return 1;
+ }
+
+ return install_extension (*filenames, force);
+}
diff --git a/src/extensions-tool/command-pack.c b/src/extensions-tool/command-pack.c
index 28c39adb7c..d98e8fa4fb 100644
--- a/src/extensions-tool/command-pack.c
+++ b/src/extensions-tool/command-pack.c
@@ -38,28 +38,6 @@ typedef struct _ExtensionPack {
static void extension_pack_free (ExtensionPack *);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ExtensionPack, extension_pack_free);
-static void
-delete_recursively (GFile *file)
-{
- g_autoptr (GFileEnumerator) file_enum = NULL;
- GFile *child;
-
- file_enum = g_file_enumerate_children (file, NULL, 0, NULL, NULL);
- if (file_enum)
- while (TRUE)
- {
- if (!g_file_enumerator_iterate (file_enum, NULL, &child, NULL, NULL))
- return;
-
- if (child == NULL)
- break;
-
- delete_recursively (child);
- }
-
- g_file_delete (file, NULL, NULL);
-}
-
static ExtensionPack *
extension_pack_new (const char *srcdir)
{
@@ -74,7 +52,7 @@ static void
extension_pack_free (ExtensionPack *pack)
{
if (pack->tmpdir)
- delete_recursively (pack->tmpdir);
+ file_delete_recursively (pack->tmpdir, NULL);
g_clear_pointer (&pack->files, g_hash_table_destroy);
g_clear_pointer (&pack->metadata, json_object_unref);
diff --git a/src/extensions-tool/commands.h b/src/extensions-tool/commands.h
index 677998fc71..247a14434c 100644
--- a/src/extensions-tool/commands.h
+++ b/src/extensions-tool/commands.h
@@ -30,5 +30,6 @@ int handle_list (int argc, char *argv[], gboolean do_help);
int handle_info (int argc, char *argv[], gboolean do_help);
int handle_create (int argc, char *argv[], gboolean do_help);
int handle_pack (int argc, char *argv[], gboolean do_help);
+int handle_install (int argc, char *argv[], gboolean do_help);
G_END_DECLS
diff --git a/src/extensions-tool/common.h b/src/extensions-tool/common.h
index 849c9caab5..860813a07b 100644
--- a/src/extensions-tool/common.h
+++ b/src/extensions-tool/common.h
@@ -54,4 +54,7 @@ void print_extension_info (GVariantDict *info,
GDBusProxy *get_shell_proxy (GError **error);
GSettings *get_shell_settings (void);
+gboolean file_delete_recursively (GFile *file,
+ GError **error);
+
G_END_DECLS
diff --git a/src/extensions-tool/completion/bash/gnome-extensions
b/src/extensions-tool/completion/bash/gnome-extensions
index bc4816afae..73b5942812 100644
--- a/src/extensions-tool/completion/bash/gnome-extensions
+++ b/src/extensions-tool/completion/bash/gnome-extensions
@@ -5,7 +5,7 @@
################################################################################
__gnome_extensions() {
- local commands="version enable disable info show list create pack"
+ local commands="version enable disable info install show list create pack"
local COMMAND=${COMP_WORDS[1]}
_init_completion -s || return
@@ -54,6 +54,13 @@ __gnome_extensions() {
;;
esac
;;
+ install)
+ if [[ $cur != -* ]]
+ then
+ _filedir zip
+ return 0
+ fi
+ ;;
esac
# Stop if we are currently waiting for an option value
diff --git a/src/extensions-tool/main.c b/src/extensions-tool/main.c
index 6a59079fb5..467f498050 100644
--- a/src/extensions-tool/main.c
+++ b/src/extensions-tool/main.c
@@ -126,6 +126,31 @@ print_extension_info (GVariantDict *info,
g_print (" %s: %s\n", _("State"), extension_state_to_string (state));
}
+gboolean
+file_delete_recursively (GFile *file,
+ GError **error)
+{
+ g_autoptr (GFileEnumerator) file_enum = NULL;
+ GFile *child;
+
+ file_enum = g_file_enumerate_children (file, NULL, 0, NULL, NULL);
+ if (file_enum)
+ while (TRUE)
+ {
+ if (!g_file_enumerator_iterate (file_enum, NULL, &child, NULL, error))
+ return FALSE;
+
+ if (child == NULL)
+ break;
+
+ if (!file_delete_recursively (child, error))
+ return FALSE;
+ }
+
+ return g_file_delete (file, NULL, error);
+}
+
+
static int
handle_version (int argc, char *argv[], gboolean do_help)
{
@@ -163,6 +188,7 @@ usage (void)
g_printerr (" show %s\n", _("Show extension info"));
g_printerr (" create %s\n", _("Create extension"));
g_printerr (" pack %s\n", _("Package extension"));
+ g_printerr (" install %s\n", _("Install extension bundle"));
g_printerr ("\n");
g_printerr (_("Use %s to get detailed help.\n"), "“gnome-extensions help COMMAND”");
}
@@ -230,6 +256,8 @@ main (int argc, char *argv[])
return handle_create (argc, argv, do_help);
else if (g_str_equal (command, "pack"))
return handle_pack (argc, argv, do_help);
+ else if (g_str_equal (command, "install"))
+ return handle_install (argc, argv, do_help);
else
usage ();
diff --git a/src/extensions-tool/man/gnome-extensions.txt b/src/extensions-tool/man/gnome-extensions.txt
index c29016d9d6..c362e4d0af 100644
--- a/src/extensions-tool/man/gnome-extensions.txt
+++ b/src/extensions-tool/man/gnome-extensions.txt
@@ -29,6 +29,8 @@ SYNOPSIS
*gnome-extensions* pack ['OPTION'...]
+*gnome-extensions* install ['OPTION'...] 'PACK'
+
DESCRIPTION
-----------
*gnome-extensions* is a utility that makes some common GNOME extensions
@@ -147,6 +149,22 @@ the current directory otherwise.
*--out-dir*='DIRECTORY':::
The directory where the pack should be created
+*install* ['OPTION'...] 'PACK'::
+Installs an extension from the bundle 'PACK'.
++
+The command unpacks the extension files and moves them to
+the expected location in the user's *$HOME*, so that it
+will be loaded in the next session.
++
+It is mainly intended for testing, not as a replacement for
+GNOME Software or the extension website. As extensions have
+privileged access to the user's session, it is advised to
+never load extensions from untrusted sources without carefully
+reviewing their content.
++
+.Options
+ *--force*:::
+ Override an existing extension
EXIT STATUS
-----------
diff --git a/src/extensions-tool/meson-src.build b/src/extensions-tool/meson-src.build
index 60834f6d36..7af5365e4e 100644
--- a/src/extensions-tool/meson-src.build
+++ b/src/extensions-tool/meson-src.build
@@ -4,6 +4,7 @@ sources = [
'command-disable.c',
'command-enable.c',
'command-info.c',
+ 'command-install.c',
'command-list.c',
'command-pack.c',
'common.h',
diff --git a/src/extensions-tool/meson.build b/src/extensions-tool/meson.build
index 2528dfd52c..3902274901 100644
--- a/src/extensions-tool/meson.build
+++ b/src/extensions-tool/meson.build
@@ -13,6 +13,7 @@ sources = [
'command-disable.c',
'command-enable.c',
'command-info.c',
+ 'command-install.c',
'command-list.c',
'command-pack.c',
'main.c'
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]