From 9e1e982bf88c23912e5bc9cfd252a842e1cde760 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 11 Oct 2017 12:18:14 +0200 Subject: [PATCH] Add flatpak config option This is currenly only used to configure the languages to install. Closes: #1098 Approved by: alexlarsson --- app/Makefile.am.inc | 1 + app/flatpak-builtins-config.c | 254 ++++++++++++++++++++++++++++++++++ app/flatpak-builtins.h | 1 + app/flatpak-main.c | 1 + common/flatpak-dir.c | 22 +++ common/flatpak-dir.h | 4 + doc/Makefile.am | 1 + doc/flatpak-config.xml | 145 +++++++++++++++++++ doc/flatpak.xml | 7 + 9 files changed, 436 insertions(+) create mode 100644 app/flatpak-builtins-config.c create mode 100644 doc/flatpak-config.xml diff --git a/app/Makefile.am.inc b/app/Makefile.am.inc index 9caf641a..e3d811fd 100644 --- a/app/Makefile.am.inc +++ b/app/Makefile.am.inc @@ -20,6 +20,7 @@ flatpak_SOURCES = \ app/flatpak-builtins-uninstall.c \ app/flatpak-builtins-list.c \ app/flatpak-builtins-info.c \ + app/flatpak-builtins-config.c \ app/flatpak-builtins-run.c \ app/flatpak-builtins-enter.c \ app/flatpak-builtins-build-init.c \ diff --git a/app/flatpak-builtins-config.c b/app/flatpak-builtins-config.c new file mode 100644 index 00000000..397c42ee --- /dev/null +++ b/app/flatpak-builtins-config.c @@ -0,0 +1,254 @@ +/* + * Copyright © 2017 Red Hat, Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: + * Alexander Larsson + */ + +#include "config.h" + +#include +#include +#include +#include + +#include + +#include "libglnx/libglnx.h" + +#include "flatpak-builtins.h" +#include "common/flatpak-dir.h" + +static gboolean opt_get; +static gboolean opt_set; +static gboolean opt_unset; +static gboolean opt_list; + +static GOptionEntry options[] = { + { "list", 0, 0, G_OPTION_ARG_NONE, &opt_list, N_("List configuration keys and values"), NULL }, + { "get", 0, 0, G_OPTION_ARG_NONE, &opt_get, N_("Get configuration for KEY"), NULL }, + { "set", 0, 0, G_OPTION_ARG_NONE, &opt_set, N_("Set configuration for KEY to VALUE"), NULL }, + { "unset", 0, 0, G_OPTION_ARG_NONE, &opt_unset, N_("Unset configuration for KEY"), NULL }, + { NULL } +}; + +static char * +parse_lang (const char *value) +{ + if (strcmp (value, "*") == 0 || + strcmp (value, "*all*") == 0) + return g_strdup (""); + return g_strdup (value); +} + +static char * +print_lang (const char *value) +{ + if (*value == 0) + return g_strdup ("*all*"); + return g_strdup (value); +} + +static char * +get_lang_default (FlatpakDir *dir) +{ + g_auto(GStrv) langs = flatpak_dir_get_default_locale_languages (dir); + + return g_strjoinv (";", langs); +} + +typedef struct { + const char *name; + const char *ostree_name; + char *(*parse)(const char *value); + char *(*print)(const char *value); + char *(*get_default)(FlatpakDir *dir); +} ConfigKey; + +ConfigKey keys[] = { + { "languages", "xa.languages", parse_lang, print_lang, get_lang_default }, +}; + +static ConfigKey * +get_config_key (const char *arg, GError **error) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (keys); i++) + { + if (strcmp (keys[i].name, arg) == 0) + return &keys[i]; + } + + flatpak_fail (error, _("Unknown configure key '%s'"), arg); + return NULL; +} + +static char * +print_config (FlatpakDir *dir, ConfigKey *key) +{ + GKeyFile *config = ostree_repo_get_config (flatpak_dir_get_repo (dir)); + g_autofree char *value = NULL; + + value = g_key_file_get_string (config, "core", key->ostree_name, NULL); + if (value == NULL) + return g_strdup ("*unset*"); + + return key->print (value); +} + +static gboolean +list_config (int argc, char **argv, FlatpakDir *dir, GCancellable *cancellable, GError **error) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (keys); i++) + { + const char *key = keys[i].name; + g_autofree char *value = print_config (dir, &keys[i]); + g_autofree char *default_value = NULL; + + g_print ("%s: %s", key, value); + + if (keys[i].get_default) + default_value = keys[i].get_default (dir); + if (default_value) + { + g_autofree char *printed = keys[i].print (default_value); + g_print (" (default: %s)", printed); + } + g_print ("\n"); + } + + return TRUE; +} + +static gboolean +get_config (int argc, char **argv, FlatpakDir *dir, GCancellable *cancellable, GError **error) +{ + ConfigKey *key; + g_autofree char *value = NULL; + + if (argc != 2) + return flatpak_fail (error, _("You must specify key")); + + key = get_config_key (argv[1], error); + if (key == NULL) + return FALSE; + + value = print_config (dir, key); + if (value) + g_print ("%s\n", value); + else + g_print ("*unset*\n"); + + return TRUE; +} + +static gboolean +set_config (int argc, char **argv, FlatpakDir *dir, GCancellable *cancellable, GError **error) +{ + ConfigKey *key; + g_autofree char *parsed = NULL; + + if (argc != 3) + return flatpak_fail (error, _("You must specify both key and value")); + + key = get_config_key (argv[1], error); + if (key == NULL) + return FALSE; + + parsed = key->parse (argv[2]); + if (!flatpak_dir_set_config (dir, key->ostree_name, parsed, error)) + return FALSE; + + return TRUE; +} + +static gboolean +unset_config (int argc, char **argv, FlatpakDir *dir, GCancellable *cancellable, GError **error) +{ + ConfigKey *key; + + if (argc != 2) + return flatpak_fail (error, _("You must specify key")); + + key = get_config_key (argv[1], error); + if (key == NULL) + return FALSE; + + if (!flatpak_dir_set_config (dir, key->ostree_name, argv[2], error)) + return FALSE; + + return TRUE; +} + +gboolean +flatpak_builtin_config (int argc, char **argv, GCancellable *cancellable, GError **error) +{ + g_autoptr(GOptionContext) context = NULL; + g_autoptr(FlatpakDir) dir = NULL; + + context = g_option_context_new (_("[KEY [VALUE]] - Manage configuration")); + g_option_context_set_translation_domain (context, GETTEXT_PACKAGE); + + if (!flatpak_option_context_parse (context, options, &argc, &argv, 0, &dir, cancellable, error)) + return FALSE; + + if (opt_get) + return get_config (argc, argv, dir, cancellable, error); + else if (opt_set) + return set_config (argc, argv, dir, cancellable, error); + else if (opt_unset) + return unset_config (argc, argv, dir, cancellable, error); + else if (opt_list) + return list_config (argc, argv, dir, cancellable, error); + else + return flatpak_fail (error, _("Must specify one on --list, --get, --set or --unset")); + + return TRUE; +} + +gboolean +flatpak_complete_config (FlatpakCompletion *completion) +{ + g_autoptr(GOptionContext) context = NULL; + g_autoptr(FlatpakDir) dir = NULL; + + context = g_option_context_new (""); + if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, 0, &dir, NULL, NULL)) + return FALSE; + + switch (completion->argc) + { + case 0: + case 1: /* REMOTE */ + flatpak_complete_options (completion, global_entries); + flatpak_complete_options (completion, options); + flatpak_complete_options (completion, user_entries); + + if (opt_set || opt_get || opt_unset) + { + int i; + for (i = 0; i < G_N_ELEMENTS (keys); i++) + flatpak_complete_word (completion, "%s", keys[i].name); + } + + break; + } + + return TRUE; +} diff --git a/app/flatpak-builtins.h b/app/flatpak-builtins.h index aa2ccf53..2970140b 100644 --- a/app/flatpak-builtins.h +++ b/app/flatpak-builtins.h @@ -84,6 +84,7 @@ BUILTINPROTO (document_info) BUILTINPROTO (document_list) BUILTINPROTO (override) BUILTINPROTO (repo) +BUILTINPROTO (config) #undef BUILTINPROTO diff --git a/app/flatpak-main.c b/app/flatpak-main.c index 97c480b3..a4756932 100644 --- a/app/flatpak-main.c +++ b/app/flatpak-main.c @@ -64,6 +64,7 @@ static FlatpakCommand commands[] = { { "uninstall", N_("Uninstall an installed application or runtime"), flatpak_builtin_uninstall, flatpak_complete_uninstall }, { "list", N_("List installed apps and/or runtimes"), flatpak_builtin_list, flatpak_complete_list }, { "info", N_("Show info for installed app or runtime"), flatpak_builtin_info, flatpak_complete_info }, + { "config", N_("Configure flatpak"), flatpak_builtin_config, flatpak_complete_config }, /* translators: please keep the leading newline and space */ { N_("\n Running applications") }, diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index e7bf7434..c1c1e87c 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -1642,6 +1642,28 @@ flatpak_dir_ensure_repo (FlatpakDir *self, return TRUE; } +gboolean +flatpak_dir_set_config (FlatpakDir *self, + const char *key, + const char *value, + GError **error) +{ + GKeyFile *config = ostree_repo_copy_config (self->repo); + + if (value == NULL) + g_key_file_remove_key (config, "core", key, NULL); + else + g_key_file_set_value (config, "core", key, value); + + if (!ostree_repo_write_config (self->repo, config, error)) + return FALSE; + + if (!ostree_repo_reload_config (self->repo, NULL, error)) + return FALSE; + + return TRUE; +} + gboolean flatpak_dir_mark_changed (FlatpakDir *self, GError **error) diff --git a/common/flatpak-dir.h b/common/flatpak-dir.h index 0ad27e06..edac361e 100644 --- a/common/flatpak-dir.h +++ b/common/flatpak-dir.h @@ -309,6 +309,10 @@ gboolean flatpak_dir_recreate_repo (FlatpakDir *self, gboolean flatpak_dir_ensure_repo (FlatpakDir *self, GCancellable *cancellable, GError **error); +gboolean flatpak_dir_set_config (FlatpakDir *self, + const char *key, + const char *value, + GError **error); gboolean flatpak_dir_mark_changed (FlatpakDir *self, GError **error); gboolean flatpak_dir_remove_appstream (FlatpakDir *self, diff --git a/doc/Makefile.am b/doc/Makefile.am index f9b7a674..cb026213 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -25,6 +25,7 @@ man1 = \ flatpak-remote-modify.1 \ flatpak-remote-ls.1 \ flatpak-install.1 \ + flatpak-config.1 \ flatpak-update.1 \ flatpak-uninstall.1 \ flatpak-list.1 \ diff --git a/doc/flatpak-config.xml b/doc/flatpak-config.xml new file mode 100644 index 00000000..725de549 --- /dev/null +++ b/doc/flatpak-config.xml @@ -0,0 +1,145 @@ + + + + + + + flatpak config + flatpak + + + + Developer + Alexander + Larsson + alexl@redhat.com + + + + + + flatpak config + 1 + + + + flatpak-config + Manage configuration + + + + + flatpak config + OPTION + KEY + VALUE + + + + + Description + + + Show and modify current configuration + + + + + + Options + + The following options are understood: + + + + + + + + Show help options and exit. + + + + + + + + Print all keys and their values + + + + + + + + Set key KEY to VALUE + + + + + + + + Unset key KEY + + + + + + + + Print value of KEY. + + + + + + + + Configure per-user installation. + + + + + + + + Configure system-wide installation. + + + + + + + + Configure the system-wide installation + specified by NAME among those defined in + /etc/flatpak/installations.d/. Using + --installation=default is equivalent to using + --system. + + + + + + + + Examples + + + $ flatpak config --set language sv;en;fi + + + + + + See also + + + flatpak1, + + + + + diff --git a/doc/flatpak.xml b/doc/flatpak.xml index babc501d..082d2d50 100644 --- a/doc/flatpak.xml +++ b/doc/flatpak.xml @@ -190,6 +190,13 @@ Show information for an installed application or runtime. + + flatpak-config1 + + + Manage flatpak configuration. + +